在 Go 语言中,我们可以编写一个函数来生成并解析标准的堆栈信息和日志信息。以下示例演示了如何实现这个功能,包括解析堆栈信息和将其格式化为结构体返回。
示例代码
package main
import (
"bytes"
"fmt"
"runtime"
"strings"
)
// StackTrace holds information about the goroutine stack trace
type StackTrace struct {
GoroutineID int
Frames []StackFrame
}
// StackFrame holds information about a single frame in the stack trace
type StackFrame struct {
File string
Line int
Function string
}
// GenerateStackTrace generates and returns the parsed stack trace of the current goroutine
func GenerateStackTrace() (*StackTrace, error) {
var buf bytes.Buffer
// Get the current stack trace
n := runtime.Stack(buf.Bytes(), false) // Get only the current goroutine's stack trace
if n == 0 {
return nil, fmt.Errorf("failed to get stack trace")
}
stackInfo := strings.Split(string(buf.Bytes()[:n]), "\n")
trace := &StackTrace{}
for _, line := range stackInfo {
if strings.Contains(line, "goroutine") {
continue // Skip lines that contain 'goroutine'
}
if len(line) > 0 {
frame, err := parseStackFrame(line)
if err == nil {
trace.Frames = append(trace.Frames, frame)
}
}
}
return trace, nil
}
// parseStackFrame parses a single line of stack trace into a StackFrame object.
func parseStackFrame(line string) (StackFrame, error) {
var file string
var lineNumber int
var function string
line = strings.TrimSpace(line)
if idx := strings.Index(line, " "); idx != -1 {
// Extract function name from beginning to first space.
function = line[:idx]
rest := line[idx+1:]
// Find last ':' for file and line number.
lastColonIndex := strings.LastIndex(rest, ":")
if lastColonIndex != -1 && lastColonIndex+1 < len(rest) {
file = rest[:lastColonIndex]
var err error
fmt.Sscanf(rest[lastColonIndex+1:], "%d", &lineNumber)
return StackFrame{File: file, Line: lineNumber, Function: function}, nil
}
}
return StackFrame{}, fmt.Errorf("invalid stack frame format: %s", line)
}
func main() {
trace, err := GenerateStackTrace()
if err != nil {
fmt.Println("Error generating stack trace:", err)
return
}
fmt.Println("Parsed Stack Trace:")
for _, frame := range trace.Frames {
fmt.Printf("Function: %s\nFile: %s\nLine: %d\n", frame.Function, frame.File, frame.Line)
}
}
说明
StackTrace
结构体:- 存储当前 goroutine 的 ID 和帧列表,每一帧用
StackFrame
表示。
- 存储当前 goroutine 的 ID 和帧列表,每一帧用
generateStackTrace
函数:- 获取当前 goroutine 的堆栈信息,并解析成
StackTrace
对象。 - 使用
runtime.Stack
获取堆栈信息,然后将结果逐行分割。 - 调用
parseStackFrame
来解析每一行并填充Frames
列表。
- 获取当前 goroutine 的堆栈信息,并解析成
parseStackFrame
函数:- 将单行的堆栈信息转换为
StackFrame
对象,提取文件名、行号和函数名。 - 格式假设是类似于
"main.main.func1 /path/to/file.go:123"
的格式。
- 将单行的堆栈信息转换为
主程序 (
main
):- 调用
GenerateStackTrace()
函数并打印出解析的堆栈信息。
- 调用
注意事项
- 此代码只会获取当前 goroutine 的堆栈信息。如果你希望获取所有 goroutines 的堆栈信息,可以在调用
runtime.Stack()
时将第二个参数设置为true
,然后进行相应的修改以支持多个 goroutines。 - 确保正确处理错误和异常情况,以便能更好地进行调试。
内容由零声教学AI助手提供,问题来源于学员提问