Go 错误:揭开 Is() 和 As() 的神秘面纱
在 Go 中,错误处理对于提供有意义的诊断和分析至关重要。实施强有力的计划。 error 包提供 Is() 和 As() 函数,分别用于确定错误相等性和提取特定细节。一个常见的误解是这些函数支持递归错误包装,从而能够展开多个嵌套错误。
但是,经过仔细检查,标准 fmt.Errorf 函数不提供递归错误包装。这意味着使用 %w 包装错误不允许完全遍历错误链。
为了解决此问题,可以定义自定义错误类型来实现错误接口并实现自己的 Is() 和As() 方法。这允许递归展开多个嵌套错误。
示例:
type customError struct { err error wrapped *customError } func (c *customError) Error() string { if c.err != nil { return c.err.Error() } return "Custom error without cause" } func (c *customError) Is(err error) bool { if c.err != nil { return errors.Is(c.err, err) } return false } func (c *customError) As(target interface{}) bool { if c.err != nil { return errors.As(c.err, target) } return false } func Wrap(errs ...error) error { var rootError *customError for i := len(errs) - 1; i >= 0; i-- { rootError = &customError{ err: errs[i], wrapped: rootError, } } return rootError }
使用此自定义错误类型,您可以轻松包装和展开多个错误并执行递归 Is() 和 As () 检查:
err := Wrap(Err1, Err2, Err3) fmt.Println(errors.Is(err, Err1)) // true fmt.Println(errors.Is(err, Err3)) // false var errType ErrType errors.As(err, &errType) fmt.Println(errType) // "my error type"
虽然此自定义实现提供递归错误展开,但有目前,Go 标准库中没有内置类型可以提供开箱即用的此功能。然而,像 github.com/pkg/errors 这样的库提供了额外的错误处理功能,包括递归解包,这可能值得在您自己的项目中考虑。
以上是Go 的 Is() 和 As() 函数如何处理递归错误包装?的详细内容。更多信息请关注PHP中文网其他相关文章!