如何判断是否相等
go相同类型的结构体可以进行之比较,定义相同的结构体可以强转后比较
指针比较是值比较,也就是是否为相同地址值
errors.Is()方法
package main
import (
"errors"
"fmt"
"reflect"
)
func main() {
TestIs()
}
type wrapped struct {
msg string
err error
}
func (e wrapped) Error() string { return e.msg }
func (e wrapped) Unwrap() error { return e.err }
func TestIs() {
err1 := errors.New("1")
fmt.Printf("%p %p\n", err1, &err1)
erra := wrapped{"wrap 2", err1}
fmt.Printf("%p %p\n", erra, &erra)
errb := wrapped{"wrap 3", erra}
fmt.Printf("%p %p\n", errb, &errb)
unwrap := errors.Unwrap(errb)
fmt.Printf("%p %p\n", unwrap, &unwrap)
fmt.Println(reflect.TypeOf(unwrap))
fmt.Println(reflect.TypeOf(erra))
fmt.Println(reflect.TypeOf(errb.err))
testCases := []struct {
err error
target error
match bool
}{
//{err1, err1, true},
//{erra, err1, true},
//{errb, err1, true},
{errb, erra, true},
}
for _, tc := range testCases {
got := errors.Is(tc.err, tc.target)
fmt.Println(got)
}
}
func Is(err, target error) bool {
if target == nil {
return err == target
}
isComparable := reflectlite.TypeOf(target).Comparable()
for {
//这里判断是否相等
if isComparable && err == target {
return true
}
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
return true
}
// TODO: consider supporting target.Is(err). This would allow
// user-definable predicates, but also may allow for coping with sloppy
// APIs, thereby making it easier to get away with them.
if err = Unwrap(err); err == nil {
return false
}
}
}
结果
0xc000010210 0xc000010200
%!p(main.wrapped={wrap 2 0xc000010210}) 0xc00000c060
%!p(main.wrapped={wrap 3 {wrap 2 0xc000010210}}) 0xc00000c0a0
%!p(main.wrapped={wrap 2 0xc000010210}) 0xc000010220
main.wrapped
main.wrapped
main.wrapped
true
可以看出wrapa 和 unwrap 的地址不同,但是值相同,所以判断为相等.如果是指针类型则做指针是否相等判断
errors.As()方法
package main
import (
"os"
"errors"
"fmt"
)
func main() {
if _, err := os.Open("non-existing"); err != nil {
var pathError *os.PathError
errNew := fmt.Errorf("wrapper~~ %w", err)
if errors.As(errNew, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
} else {
fmt.Println(err)
}
}
}
Failed at path: non-existing
遍历errNew unwrap到target类型的值后赋值到target指向地址
参考
代码改造自官方文档,写作来源来自下面地址:
[Go语言(golang)新发布的1.13中的Error Wrapping深度分析](www.cnblogs.com/sunsky303/p…)