error.Wrap 和 error.WithMessage 之间有什么区别

nak*_*kem 3 go

github.com/pkg/errors

这是Wrap(err error, msg string) https://pkg.go.dev/github.com/pkg/errors#Wrap

这是WithMessage(err error, msg string) https://pkg.go.dev/github.com/pkg/errors#WithMessage

这两个函数都实现了接口causer https://pkg.go.dev/github.com/pkg/errors#Cause

这段代码适用于errors.WithMessage,尽管我认为我应该使用errors.Wrapforerrors.Cause

func main() {
    err := errors.New("first")
    err1 := errors.WithMessage(err, "tmp")
    err2 := errors.WithMessage(err1, "tmp")
    err3 := errors.WithMessage(err2, "tmp")
    fmt.Printf("%s", errors.Cause(err3))
}
Run Code Online (Sandbox Code Playgroud)

Output: first

Adr*_*ian 5

不同之处在于Wrap包括调用堆栈。如果你点击 Go 文档中的某个函数名称,它就会带你到源代码,你可以看到这两个函数都非常短小简单,只有一处不同;whileWithMessage使用给定的消息和原因(您传入的错误)​​创建一个新错误,并接受此错误并再次Wrap包装它,如下所示:

&withStack{
    err,
    callers(),
}
Run Code Online (Sandbox Code Playgroud)

err是它刚刚创建的新错误(与您从 中得到的完全相同WithMessage)并callers填充调用堆栈。文档中指出了这一点(强调我的):

Wrap 返回一个错误,并在调用 Wrap 时用堆栈跟踪注释 err

中没有提到,WithMessage因为它不是由该函数完成的。