目录

go 如何打印错误时代码堆栈信息(使用库 pkg error 包)

背景

打印错误 error 日志时,仅有错误信息,没有错误代码的堆栈信息,这在问题排查上比较困难,具体代码如下

package main

import (
    "errors"
    "fmt"
)
func main() {
    err := NewErr("this is err msg")
    fmt.Printf("%v\n", err)
}

this is err msg

没有错误的堆栈信息(也就是代码的调用执行信息),只是单纯的根据 log 信息有时候很难排查具体出现问题的代码块,如果有堆栈信息,那么就可以快速定位代码出现问题的代码行

那么如何才能实现打印数据,同时输出 trace 调用栈信息呢?答案:使用 第三方库 github.com/pkg/errors 替换官方库 errors 包(基本上是无损替换,pkg errors 包兼容 errors 包)

pkg errors 包

使用 github.com/pkg/errors 替换 errors 包,可以无缝替换,因为 pkg/errors 包的 api 和 errors 几乎一致,但是功能更加强大

打印错误堆栈:

替换导包,并且使用 %+v 占位符,否则无法打印堆栈

package main

import (
    "github.com/pkg/errors"
    "fmt"
)
func main() {
    err := NewErr("this is err msg")
    fmt.Printf("%+v\n", err)
}
func NewErr(s string) error {
    return errors.New(s)
}

this is err msg main.NewErr xxxx/main.go:43 main.main xxxx/main.go:38 runtime.main xxxx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.4.darwin-arm64/src/runtime/proc.go:272 runtime.goexit xxxx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.4.darwin-arm64/src/runtime/asm_arm64.s:1223

也可以对已存在的 err 进行包装,包含堆栈信息

func main() {
    err := NewNoTraceErr("this is err msg")
    err = errors.WithStack(err)
    fmt.Printf("%+v\n", err)
}
func NewNoTraceErr(s string) error {
    return fmt.Errorf("err:%s", s)
}

err:this is err msg main.main xxx/go/src/it******.com/learn-go/main.go:39 runtime.main …

此时你会发现堆栈的信息只能追踪到:err = errors.WithStack(err)

所以:堆栈只能追踪到:只有在使用了 pkg/errors 包封装的代码位置

第三方库的代码绝大多数都没有使用 github.com/pkg/errors

⚠️⚠️:

所以在使用第三方库的时,err 应该用 errors.WithStack(err) 或者 errors.Wrap(err,“自定义错误信息”) 进行封装,然后再往上抛

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/go-pkg-err/

备用原文链接: https://blog.fiveyoboy.com/articles/go-pkg-err/