我正在使用Go中的错误包装,并有一个返回包装的自定义错误类型的函数.我想要做的是迭代预期错误的列表,并测试函数的输出是否包装了这些预期错误.
我发现将定制错误放在[]error
内意味着定制错误的类型将是*fmt.wrapError
,这意味着errors.As()
几乎总是返回TRUE.
作为示例,请考虑以下代码:
package main
import (
"errors"
"fmt"
)
type AnotherError struct {
}
func (e *AnotherError) Error() string {
return "another error"
}
type MissingAttrError struct {
missingAttr string
}
func (e *MissingAttrError) Error() string {
return fmt.Sprintf("missing attribute: %s", e.missingAttr)
}
func DoSomething() error {
e := &MissingAttrError{missingAttr: "Key"}
return fmt.Errorf("DoSomething(): %w", e)
}
func main() {
err := DoSomething()
expectedErrOne := &MissingAttrError{}
expectedErrTwo := &AnotherError{}
expectedErrs := []error{expectedErrOne, expectedErrTwo}
fmt.Printf("Is err '%v' type '%T'?: %t\n", err, expectedErrOne, errors.As(err, &expectedErrOne))
fmt.Printf("Is err '%v' type '%T'?: %t\n", err, expectedErrTwo, errors.As(err, &expectedErrTwo))
for i := range expectedErrs {
fmt.Printf("Is err '%v' type '%T'?: %t\n", err, expectedErrs[i], errors.As(err, &expectedErrs[i]))
}
}
其输出结果是
Is err 'DoSomething(): missing attribute: Key' type '*main.MissingAttrError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*main.AnotherError'?: false
Is err 'DoSomething(): missing attribute: Key' type '*fmt.wrapError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*fmt.wrapError'?: true
理想情况下,我希望输出为
Is err 'DoSomething(): missing attribute: Key' type '*main.MissingAttrError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*main.AnotherError'?: false
Is err 'DoSomething(): missing attribute: Key' type '*main.MissingAttrError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*main.AnotherError'?: false
拥有错误切片的原因是我希望能够定义每个测试用例条目的预期错误列表.假设我知道,为函数提供特定的输入将使它沿着一条应该返回包装特定错误的错误的路径前进.
如何将[]error
切片中的*fmt.wrapError
类型转换回原始类型,以便可以在error.As
中使用它?
我知道我可以用.(AnotherError)
将其强制为特定类型,但要使其在迭代切片时起作用,我必须对函数可能返回的每个可能的错误执行此操作,不是吗?)