首页 >后端开发 >Golang >如何在 Go 中实现真正的递归错误包装和展开?

如何在 Go 中实现真正的递归错误包装和展开?

Susan Sarandon
Susan Sarandon原创
2024-12-12 14:52:10572浏览

How Can I Achieve True Recursive Error Wrapping and Unwrapping in Go?

Go 中使用递归 Is() 和 As() 进行错误包装

许多开发人员建议在 Go 中使用 fmt.Errorf 和 %w 动词来包装错误,但是这个方法不提供真正的递归包装。要使用 Is() 和 As() 递归检查错误,可以使用自定义错误类型。

递归的自定义错误类型

这里有一个自定义错误类型 errorChain,支持错误包装和递归检查:

type errorChain struct {
    err  error
    next *errorChain
}

func Wrap(errs ...error) error {
    out := errorChain{err: errs[0]}

    n := &out
    for _, err := range errs[1:] {
        n.next = &errorChain{err: err}
        n = n.next
    }
    return out
}

将 Is() 和 As() 添加到自定义中Type

启用递归检查的关键是在自定义类型上实现 Is() 和 As() 方法。这些方法允许对链中包含的错误进行错误比较,而不是链本身:

func (c errorChain) Is(err error) bool { return errors.Is(c.err, err) }

func (c errorChain) As(target any) bool { return errors.As(c.err, target) }

使用 errorChain

使用这些方法,您可以包装错误并执行递归检查:

errs := Wrap(errors.New("error 0"), errors.New("error 1"), errors.New("error 2"))

fmt.Println(errors.Is(errs, errors.New("error 0")))  // true
fmt.Println(errors.Is(errs, errors.New("error 1")))  // true
fmt.Println(errors.Is(errs, errors.New("error 2")))  // true

使用 Unwrap() 迭代Chain

errorChain 中的 Unwrap() 方法允许您遍历链中包装的错误:

var currentError error = errs
for {
    currentError = errors.Unwrap(currentError)
    if currentError == nil {
        break
    }
    fmt.Println(currentError)
}

此示例打印链中的所有错误:

error 0
error 1
error 2

以上是如何在 Go 中实现真正的递归错误包装和展开?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn