仅使用标准库,如何在自定义错误中包装错误?

时间:2020-04-24 11:13:28

标签: go error-handling

从Go 1.13开始,我们可以链接错误,解开错误并通过errors.Is()errors.As()检查链接中的任何错误是否与预期错误相符。

要包裹一个错误,您要做的就是如下使用%w动词和fmt.Errorf()

fmt.Errorf("Custom message: %w", err)

这很容易,它会将err包裹在另一个消息中,并附加一条消息。但是,可以说我需要的不仅仅是消息,而是更多的上下文。如何在自己的结构化自定义错误中包装err?仅使用Go 1.13+标准库。

2 个答案:

答案 0 :(得分:2)

您可以创建一个新的错误类型,该错误类型可以包装其他错误,同时提供其他结构化信息。

type MyError struct {
    Inner error
    // Provide any additional fields that you need.
    Message string
    AdditionalContext string 
}

// Error is mark the struct as an error.
func (e *MyError) Error() string {
    return fmt.Sprintf("error caused due to %v; message: %v; additional context: %v", e.Inner, e.Message, e.AdditionalContext)
}

// Unwrap is used to make it work with errors.Is, errors.As.
func (e *MyError) Unwrap() error {
    // Return the inner error.
    return e.Inner
}

// WrapWithMyError to easily create a new error which wraps the given error.
func WrapWithMyError(err error, message string, additionalContext string) error {
    return &MyError {
        Inner: err,
        Message: message,
        AdditionalContext: additionalContext,
    }
}

您需要实现ErrorUnwrap接口才能使用errors.Iserrors.As的新功能。

答案 1 :(得分:0)

错误是一个界面(error() string满足),因此您可以将另一个错误类型设置为:

type myCustomError struct {
  Message    string
  StatusCode int
}

func (m myCustomError) error() string {
  return fmt.Sprintf("Code %d: \tMessage: %s", m.StatusCode, m.Message) 
}

现在您可以使用

作为自定义错误抛出的错误
_, err := doStuff()
var v myCustomError
if errors.As(err, &v) {
   // now v is parsed 
}