如何解决使用/ pkg / errors和golang 1.13格式化动词%w进行错误处理
我想用堆栈跟踪注释错误,因此我正在使用/ pkg / errors包。
Go 1.13在包装错误中添加了%w-格式动词。
以下不使用%w的程序会打印出一个不错的堆栈跟踪:
https://play.golang.org/p/eAwMrwqjCWX
以下仅使用%w进行略微修改的程序:
https://play.golang.org/p/am34kdC0E3o
我应该如何将%w与错误包装和堆栈跟踪一起使用?
解决方法
原因是errors.Errorf
初始化了新的fundamental
错误类型(在pkg/errors
中)。如果您要查看其方法Format(s fmt.State,verb rune)
(在您进行log.Printf
时触发):
func (f *fundamental) Format(s fmt.State,verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
io.WriteString(s,f.msg)
f.stack.Format(s,verb)
return
}
fallthrough
case 's':
io.WriteString(s,f.msg)
case 'q':
fmt.Fprintf(s,"%q",f.msg)
}
}
因此,您看到它仅打印io.WriteString(s,f.msg)
。
另外,Errorf
是:
func Errorf(format string,args ...interface{}) error {
return &fundamental{
msg: fmt.Sprintf(format,args...),stack: callers(),}
}
因为这一行:fmt.Sprintf(format,args...)
,您会看到go vet的错误(您无法将%w
传递给Sprintf
),而在打印错误msg时,您只会看到:
Es gab einen Fehler: %!w(*errors.fundamental=&{failing unconditionally 0xc0000a2000})
使用Wrap
方法时,会得到withStack
错误类型,其错误类型为Format
:
func (w *withStack) Format(s fmt.State,verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s,"%+v",w.Cause())
w.stack.Format(s,w.Error())
case 'q':
fmt.Fprintf(s,w.Error())
}
}
感谢fmt.Fprintf(s,w.Cause())
这一行,您会看到一个不错的递归堆栈跟踪。
基本上,您需要像这样使用%w
:
fmt.Errorf("got error: %w",err)
但是如果您要打印纸叠,这将无济于事。
您可能要做的是为自己实现一个递归打印堆栈跟踪的函数,该函数将在fmt
或pkg/errors
的错误链上起作用:
type stackTracer interface {
StackTrace() errors.StackTrace
}
type unwrapper interface {
Unwrap() error
}
func printStack(err error) {
if err == nil {
return
}
if ster,ok := err.(stackTracer); ok {
fmt.Printf("%+v",ster)
}
if wrapped,ok := err.(unwrapper); ok {
printStack(wrapped.Unwrap())
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。