Golang Go语言中求教如何打印错误调用栈

发布于 1周前 作者 eggper 来自 Go语言

null
Golang Go语言中求教如何打印错误调用栈

11 回复

runtime.Callers

更多关于Golang Go语言中求教如何打印错误调用栈的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


用 %w 就行,好像 1.18 开始支持的吧

我一般这样写:

func CallStack(skip int) string {
pcs := make([]uintptr, 32)
numFrames := runtime.Callers(skip, pcs)
for numFrames == len(pcs) {
pcs = make([]uintptr, len(pcs)*2)
numFrames = runtime.Callers(skip, pcs)
}
pcs = pcs[:numFrames]
frames := runtime.CallersFrames(pcs)
sb := strings.Builder{}
for frame, more := frames.Next(); more; frame, more = frames.Next() {
sb.WriteString(frame.Function)
sb.WriteByte(’\n’)
sb.WriteByte(’\t’)
sb.WriteString(frame.File)
sb.WriteByte(’:’)
sb.WriteString(strconv.Itoa(frame.Line))
}
return sb.String()
}

没法,你得自己写个 error 的 wrap 方法,在 wrap 的时候加上行号,最后再打印出来就行了
zap 那个调用栈是反的,没用,很鸡肋

可以用第三方的 error ,如 https://github.com/pkg/errors ;当然本质是调用 runtime 里的函数

自己实现 error 。每次创建时,收集调用堆栈。但建议用专用的方法输出调用堆栈。

欢迎使用 https://github.com/gookit/goutilerrorx

go<br>err := errorx.New("the error message")<br><br> fmt.Println(err)<br>

输出类似:

<br>the error message<br>STACK:<br><a target="_blank" href="http://github.com/gookit/goutil/errorx_test.returnXErr()" rel="nofollow noopener">github.com/gookit/goutil/errorx_test.returnXErr()</a><br> /Users/inhere/Workspace/godev/gookit/goutil/errorx/errorx_test.go:21<br><a target="_blank" href="http://github.com/gookit/goutil/errorx_test.returnXErrL2()" rel="nofollow noopener">github.com/gookit/goutil/errorx_test.returnXErrL2()</a><br> /Users/inhere/Workspace/godev/gookit/goutil/errorx/errorx_test.go:25<br><a target="_blank" href="http://github.com/gookit/goutil/errorx_test.TestNew()" rel="nofollow noopener">github.com/gookit/goutil/errorx_test.TestNew()</a><br> /Users/inhere/Workspace/godev/gookit/goutil/errorx/errorx_test.go:29<br>testing.tRunner()<br> /usr/local/Cellar/go/1.18/libexec/src/testing/testing.go:1439<br>runtime.goexit()<br> /usr/local/Cellar/go/1.18/libexec/src/runtime/asm_amd64.s:1571<br>

可以使用 github.com/pkg/errors 实现打印调用堆栈,在 pkg/errors 中除了可以使用 withMessage 附加错误信息以外还可以 withStack 附加堆栈信息,源码如下:

// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: message,
}
return &withStack{
err,
callers(),
}
}

在Go语言中,当你遇到错误并希望打印出错误的调用栈(stack trace)时,可以使用runtimefmt包中的相关功能。以下是一个简单的示例,展示了如何捕获和打印错误的调用栈:

package main

import (
	"fmt"
	"runtime"
)

func main() {
	defer func() {
		if r := recover(); r != nil {
			printStack()
			fmt.Println("Recovered from panic:", r)
		}
	}()

	someFunction()
}

func someFunction() {
	err := someOtherFunction()
	if err != nil {
		panic(err)
	}
}

func someOtherFunction() error {
	return fmt.Errorf("an error occurred")
}

func printStack() {
	const size = 1024
	buf := make([]byte, size)
	n := runtime.Stack(buf, true)
	fmt.Print(string(buf[:n]))
}

在这个例子中,someFunction调用了someOtherFunction,后者返回了一个错误。someFunction在遇到错误时触发panic,随后被main函数中的defer捕获并调用printStack函数打印调用栈。

runtime.Stack函数将当前goroutine的栈信息写入提供的缓冲区,并返回写入的字节数。这里我们使用了一个大小为1024字节的缓冲区,通常足够捕获大多数情况下的栈信息。如果需要更详细的栈信息,可以增加缓冲区的大小。

这种方法对于调试和定位错误非常有用,可以帮助你快速理解错误发生的上下文。

回到顶部