我正在尝试了解如何在实现相同界面时检查两个对象是否相同。
以下是示例代码:
package main
import (
"fmt"
)
type shout interface {
echo()
}
type a struct {}
func (*a) echo () {
fmt.Println("a")
}
type b struct {}
func (*b) echo () {
fmt.Println("b")
}
func compare(a, b shout) {
//fmt.Println(&a, &b)
if a == b {
fmt.Println("same")
} else {
fmt.Println("not same")
}
}
func main() {
a1 := &a{}
b1 := &b{}
a2 := &a{}
a1.echo()
b1.echo()
compare(a1, b1)
compare(a1, a2)
compare(a1, a1)
}
https://play.golang.org/p/qo9XnbthMw
结果是:
not same
not same
same
a1和a2不一样
但如果取消注释第22行
fmt.Println(&a, &b)
结果是:
0x1040a120 0x1040a128
not same
0x1040a140 0x1040a148
same
0x1040a158 0x1040a160
same
有谁能弄明白这里发生了什么? Golang编译器是否优化了某些东西?
由于
答案 0 :(得分:2)
这似乎是https://github.com/golang/go/issues/8938的一个更复杂的例子。
Go规范的相关部分是https://golang.org/ref/spec#Comparison_operators
指向不同零大小变量的指针可能相等也可能不相等。
和https://golang.org/ref/spec#Size_and_alignment_guarantees
两个不同的零大小变量在内存中可能具有相同的地址。
基于上面链接的问题的标题(cmd/compile: optimisations change the behaviour of *struct{}
),差异是由编译器优化引起的。
答案 1 :(得分:0)
这是预期的行为。对于背景,==
是一个运算符,用于比较两个对象的值。这称为对象相等。比较它们的指针值或它们的身份是不同的。请参阅this similar post上的热门答案。
当您询问a1 == b1
时,您会收到false
因为a1
是a
结构的实例,而b1
是b
的实例1}}结构。因此,即使它们实现相同的接口,它们彼此 ==
。考虑一下a
结构和b
结构,它们在两者中都实现了其他不同的方法(因此a
有一个额外的方法foo()
而b
还有一个方法bar()
)。虽然a
和b
会实现相同的界面,但它们不会相同,您也不会期望或想要它们。
当您询问是否a1 == a2
时,您收到的是真的,因为a1
和a2
只是同一结构的单独实例。引用我上面链接的帖子,a1
和a2
相等,但不共享相同的身份。
最后,当你询问是否a1 == a1
时,你问的是同一个对象的相同实例是否等于它自己,当然这是真的。在这种情况下,a1
与a1
共享平等和身份。
答案 2 :(得分:0)
您应该使用reflect.DeepEqual
来比较struct,slice和map。
package main
import (
"fmt"
)
type a struct{}
func main() {
a1 := &a{}
a2 := &a{}
fmt.Printf("%p\n", a1)
if a1 == a2 {
fmt.Println("same")
} else {
fmt.Println("not same")
}
}
结果是:
0x196a9c
not same
使用reflect.DeepEqual
,如下所示:
package main
import (
"fmt"
"reflect"
)
type a struct{}
func main() {
a1 := &a{}
a2 := &a{}
fmt.Printf("%p\n", a1)
if a1 == a2 {
fmt.Println("same")
} else {
fmt.Println("not same")
}
fmt.Println(reflect.DeepEqual(a1, a2))
}
结果是:
0x196a9c
same
true
我猜是golang编译器优化。