在我看来,在 Go 中“包装”错误的“方式”是使用带有 %w 动词的 fmt.Errof
https://go.dev/blog/go1.13-errors
但是,fmt.Errorf 不会递归地包装错误。无法使用它来包装三个先前定义的错误(Err1、Err2 和 Err3),然后使用 Is() 检查结果并为这三个错误中的每一个都获取 true。
最后编辑:
多亏了@mkopriva 的回答和下面的评论,我现在有了一种直接的方法来实现它(尽管,我仍然很好奇是否有某种标准类型可以做到这一点)。由于没有示例,我创建示例的尝试失败了。我缺少的部分是在我的类型中添加一个Is
和As
方法。因为自定义类型需要包含错误和指向下一个错误的指针,所以自定义Is
和As
方法允许我们比较自定义类型中包含的错误,而不是自定义类型本身。
这是一个工作示例:https ://go.dev/play/p/6BYGgIb728k
以上链接的亮点
type errorChain struct {
err error
next *errorChain
}
//These two functions were the missing ingredient
//Defined this way allows for full functionality even if
//The wrapped errors are also chains or other custom types
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) }
//Omitting Error and Unwrap methods for brevity
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
}
}
虽然 Go源代码特别提到了定义Is
方法的能力,但该示例并未以可以解决我的问题的方式实现它,并且讨论并未立即明确表明需要利用errors.Is
.
现在回到原来的帖子:
Go 中是否有内置的东西可以正常工作?
我尝试自己制作一个(几次尝试),但遇到了不良问题。这些问题源于这样一个事实,即 Go 中的错误似乎是通过地址进行比较的。即,如果 Err1 和 Err2 指向同一事物,则它们是相同的。
这给我带来了问题。我可以天真地获取errors.Is
和errors.As
使用自定义错误类型递归工作。这很简单。
创建一个实现错误接口的类型(有一个Error() string
方法)
该类型必须有一个代表包装错误的成员,该成员是指向其自身类型的指针。
实现一个Unwrap() error
返回包装错误的方法。
实现一些将一个错误与另一个错误包装起来的方法
好像不错 但是有麻烦。
由于错误是指针,如果我做类似的事情myWrappedError = Wrap(Err1, Err2)
(在这种情况下假设Err1
被包装Err2
)。不仅 willerrors.Is(myWrappedError, Err1)
和errors.Is(myWrappedError, Err2)
return true,而且 will 也会errors.Is(Err2, Err1)
如果需要 makemyOtherWrappedError = Wrap(Err3, Err2)
和稍后调用errors.Is(myWrappedError, Err1)
它现在将返回 false!进行myOtherWrappedError
更改myWrappedError
。
我尝试了几种方法,但总是遇到相关问题。
这可能吗?是否有执行此操作的 Go 库?
繁星coding
潇潇雨雨
一只萌萌小番薯
翻阅古今
相关分类