用 %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()
}
debug.Stack
可以用第三方的 error ,如 https://github.com/pkg/errors ;当然本质是调用 runtime 里的函数
欢迎使用 https://github.com/gookit/goutil 的 errorx
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)时,可以使用runtime
和fmt
包中的相关功能。以下是一个简单的示例,展示了如何捕获和打印错误的调用栈:
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字节的缓冲区,通常足够捕获大多数情况下的栈信息。如果需要更详细的栈信息,可以增加缓冲区的大小。
这种方法对于调试和定位错误非常有用,可以帮助你快速理解错误发生的上下文。