Error 封装

下面提供三种主要的方法来传递函数调用失败返回的错误:

  • 如果想要维护原始错误类型并且不需要添加额外的上下文信息,就直接返回原始错误。
  • 使用 "pkg/errors".Wrap 来增加上下文信息,这样返回的错误信息中就会包含更多的上下文信息,并且通过 "pkg/errors".Cause 可以提取出原始错误信息。
  • 如果调用方不需要检测或处理特定的错误情况,就直接使用 fmt.Errorf

情况允许的话建议增加更多的上下文信息来代替诸如 "connection refused" 之类模糊的错误信息。返回 "failed to call service foo: connection refused" 用户可以知道更多有用的错误信息。

在将上下文信息添加到返回的错误时,请避免使用 "failed to" 之类的短语以保持信息简洁,这些短语描述的状态是显而易见的,并且会随着错误在堆栈中的传递而逐渐堆积:

BadGood
  1. s, err := store.New()
  2. if err != nil {
  3. return fmt.Errorf(
  4. "failed to create new store: %s", err)
  5. }
  1. s, err := store.New()
  2. if err != nil {
  3. return fmt.Errorf(
  4. "new store: %s", err)
  5. }
  1. failed to x: failed to y: failed to create new store: the error
  1. x: y: new store: the error

但是,如果这个错误信息是会被发送到另一个系统时,必须清楚的表明这是一个错误(例如,日志中 err 标签或者 Failed 前缀)。

另见 Don't just check errors, handle them gracefully