从Go 1.13开始,我们有了新的有用的方法来找出错误的类型,即使我们使用错误包装。如果我们想检查一个给定的错误是否符合另一个特定的错误,我们需要使用 Is()函数从 errors包中的函数。如果我们对错误是否属于某个给定的类型感兴趣,我们应该调用 As()函数。
Is函数
在下面的例子中,我们可以看到,函数validateInput ,返回一个错误badInput 。这个错误被ErrBadInput 包裹在一个由 fmt.Errorf().使用该 Is(err, target error) bool函数,我们可以检测到ErrBadInput ,即使它被包装了,因为这个函数会检查被包装的错误链中的任何错误是否与目标匹配。因此,这种形式应该优于比较if err == ErrBadInput 。
package main
import (
"errors"
"fmt"
)
const badInput = "abc"
var ErrBadInput = errors.New("bad input")
func validateInput(input string) error {
if input == badInput {
return fmt.Errorf("validateInput: %w", ErrBadInput)
}
return nil
}
func main() {
input := badInput
err := validateInput(input)
if errors.Is(err, ErrBadInput) {
fmt.Println("bad input error")
}
}
输出。
bad input error
As函数
类似于 Is(),该 As(err error, target interface{}) bool检查被包装的错误链中的任何错误是否与目标匹配。不同的是,这个函数检查错误是否有一个特定的类型,不像 Is(),后者检查它是否是一个特定的错误对象。因为 As考虑整个错误链,它应该优于类型断言if e, ok := err.(*BadInputError); ok 。
target参数的As(err error, target interface{}) bool函数的参数应该是一个指向错误类型的指针,在本例中是*BadInputError
package main
import (
"errors"
"fmt"
)
const badInput = "abc"
type BadInputError struct {
input string
}
func (e *BadInputError) Error() string {
return fmt.Sprintf("bad input: %s", e.input)
}
func validateInput(input string) error {
if input == badInput {
return fmt.Errorf("validateInput: %w", &BadInputError{input: input})
}
return nil
}
func main() {
input := badInput
err := validateInput(input)
var badInputErr *BadInputError
if errors.As(err, &badInputErr) {
fmt.Printf("bad input error occured: %s\n", badInputErr)
}
}
输出。
bad input error occured: bad input: abc