如果一个函数或方法调用失败时,有三种方式来传播错误:
- 如果没有额外的上下文环境需要添加并且你想保持原始的错误类型的话,请返回原始的错误。
- 通过
"pkg/errors".Wrap添加上下文环境,以至于错误消息能够提供更多的上下文信息,并且
"pkg/errors".Cause可以用来提取原始的错误。
如果调用者无需断言和处理指定的错误的情况下,请使用
fmt.Errorf
强烈
建议在可能的情况下,请添加上下文,这样就不会出现“connection refused”这样模糊的错误,你会得到更多有用的错误描述信息,例如“call service foo: connection refused”。
当为返回的错误添加上下文时,避免使用像“failed to”这样的短语来保持上下文的简洁,这些短语陈述了明显的错误,并在错误通过堆栈溢出时堆积起来。
Bad
s, err := store.New()
if err != nil {
//没有额外的上下文环境需要添加
return fmt.Errorf(
"failed to create new store: %s", err)
}
//错误传播的话,容易操作错误信息的模糊
//failed to x: failed to y: failed to create new store: the error
Good
s, err := store.New()
if err != nil {
return fmt.Errorf(
"new store: %s", err)
}
//错误传播的话,错误消息简单明了
//x: y: new store: the error
一个errors.Wrap 的例子:
package main
import (
"fmt"
"github.com/pkg/errors"
)
func main() {
cause := errors.New("whoops")
err := errors.Wrap(cause, "oh noes")
fmt.Println(err)
}
Output:
oh noes: whoops
一旦错误被发送至另外一个系统,就应该明确此消息是错误消息(例如使用err
标记,或在日志中以”Failed”为前缀)。
另请参见 Don't just check errors, handle them gracefully. 不要只是检查错误,要优雅地处理错误