Go语言errors包中类型断言至单参数匿名接口的疑问
Go errors.Is内部断言逻辑疑问解答
疑问1:为什么能将err断言到单参数Is方法的匿名接口?
你混淆了包级函数errors.Is和自定义error类型的Is方法。
包级的errors.Is(err, target error)是两个参数的工具函数,但这里的断言err.(interface{ Is(error) bool }),检查的是err的具体类型有没有实现一个名为Is、接收一个error参数、返回bool的方法——这是自定义error类型可以实现的方法,用来让errors.Is工具函数调用它来判断当前error是否匹配target。
举个简单的自定义error例子:
type MyErr struct{} func (e MyErr) Is(target error) bool { _, ok := target.(MyErr) return ok }
当你调用errors.Is(MyErr{}, MyErr{})时,内部就会触发这个断言,调用MyErr.Is方法来判断匹配,而不是用默认的相等性检查。
疑问2:是否有其他类似的例外规则?
这不是例外,是Go语言鸭子类型接口的正常行为:只要类型的方法签名和接口完全一致(方法名、参数类型、返回值类型都匹配),就自动实现该接口,不需要显式声明。
除了errors.Is对应的Is(error) bool方法,Go标准库还有类似的模式:
errors.As工具函数会检查err的类型是否实现了As(interface{}) bool方法,用来自定义类型断言的逻辑fmt.Stringer接口要求实现String() string方法,任何有这个方法的类型都可以直接用fmt.Println输出其字符串表示
验证示例代码
package main import ( "errors" "fmt" ) type CustomErr struct { msg string } func (e CustomErr) Error() string { return e.msg } func (e CustomErr) Is(target error) bool { t, ok := target.(CustomErr) if !ok { return false } return e.msg == t.msg } func main() { err1 := CustomErr{msg: "test error"} err2 := CustomErr{msg: "test error"} err3 := errors.New("test error") fmt.Println(errors.Is(err1, err2)) // 输出 true,因为调用了CustomErr.Is fmt.Println(errors.Is(err1, err3)) // 输出 false }
内容的提问来源于stack exchange,提问作者James Buzzger
相关产品推荐
相关产品推荐

