英文:
Is it possible to define equality for named types/structs?
问题
在阅读了一个关于在Go中使用切片作为map键的相关问题后,我对Go中的相等性产生了好奇。
我知道在Java的Object
中可以重写equals
方法。在Go中是否有类似的方法来定义如何检查用户定义的类型/结构体的相等性?如果有的话,那么就可以解决上述问题。我尝试使用interface{}
值,但是收到了错误消息panic: runtime error: hash of unhashable type []int
。
英文:
After reading a related question about using slices in maps, I became curious about equality in Go.
I know it's possible to override the equals
method of a Java Object
. Is there a similar way to define how Go checks user defined types/structs for equality? If so, there would be a workaround for the issue referenced above. I thought using interface{}
values might offer a solution but I received the error message panic: runtime error: hash of unhashable type []int
.
答案1
得分: 33
不。你不能修改等号运算符,并且没有内置的方法来添加对自定义类型使用==
语法的支持。相反,你应该使用reflect.DeepEqual
来比较指针值。
Go支持检查结构体的相等性。
type Person struct {
Name string
}
a := Person{"Bill DeRose"}
b := Person{"Bill DeRose"}
a == b // true
对于指针字段(以你想要的方式),它不起作用,因为指针地址是不同的。
type Person struct {
Friend *Person
}
a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}
a == b // false
你可以导入reflect
包,并使用reflect.DeepEqual
来比较。
import "reflect"
a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}
reflect.DeepEqual(a, b) // true
请记住,这里有一些注意事项。
通常,
DeepEqual
是Go的==
运算符的递归放宽。然而,这个想法是不可能实现的,因为会存在一些不一致性。具体来说,一个值可能与自身不相等,要么是因为它是func
类型(一般情况下是不可比较的),要么是因为它是浮点数的NaN
值(在浮点数比较中不等于自身),要么是因为它是包含这样的值的数组、结构体或接口。
英文:
No. You can't modify the equality operator and there is no built-in way to add support for custom types to use ==
syntax. Instead you should compare the pointer values using reflect.DeepEqual
.
Go supports equality checking structs.
type Person struct {
Name string
}
a := Person{"Bill DeRose"}
b := Person{"Bill DeRose"}
a == b // true
It won't work with pointer fields (in the way you want) because the pointer addresses are different.
type Person struct {
Friend *Person
}
a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}
a == b // false
import "reflect"
a := Person{Friend: &Person{}}
b := Person{Friend: &Person{}}
reflect.DeepEqual(a, b) // true
Keep in mind there are caveats.
> In general DeepEqual is a recursive relaxation of Go's == operator. However, this idea is impossible to implement without some inconsistency. Specifically, it is possible for a value to be unequal to itself, either because it is of func type (uncomparable in general) or because it is a floating-point NaN value (not equal to itself in floating-point comparison), or because it is an array, struct, or interface containing such a value.
答案2
得分: 27
不,这是不可由用户定义的。Go语言对于相等性有严格的规定,甚至对于可比性也有规定,而可比性本身是基于可赋值性的。请参考规范中的比较运算符部分。
英文:
No, this is not user-definable. Go has strict rules what counts as equal, and even what is comparable which itself is based on assignability. Take a look at the Comparison operators section of the spec.
答案3
得分: 10
Go语言本身没有标准的比较方法(截至go 1.13)。
然而,比较工具可以提供自己的方式来支持比较。
函数cmp.Equal
(来自google/go-cmp/cmp)通过定义一个Equal方法来支持自定义类型比较器:
• 如果值具有形式为(T) Equal(T) bool
或(T) Equal(I) bool
的Equal方法,其中T
可赋值给I
,则使用x.Equal(y)
的结果,即使x
或y
为nil。否则,不存在这样的方法,评估将继续到下一个规则。
英文:
There's no standard in Go language itself, yet (go 1.13).
However, comparison utilities could provide their own way to support it.
Function cmp.Equal
(from google/go-cmp/cmp) supports definition of custom type comparator via definition of a Equal method:
> • If the values have an Equal method of the form "(T) Equal(T) bool"
or "(T) Equal(I) bool"
where T
is assignable to I
, then use the result of x.Equal(y)
even if x
or y
is nil. Otherwise, no such method exists and evaluation proceeds to the next rule.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论