当fmt.Println()时golang编译器会做什么

时间:2016-12-28 08:11:12

标签: go interface

我正在尝试了解如何在实现相同界面时检查两个对象是否相同。

以下是示例代码:

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编译器是否优化了某些东西?

由于

3 个答案:

答案 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因为a1a结构的实例,而b1b的实例1}}结构。因此,即使它们实现相同的接口,它们彼此 ==。考虑一下a结构和b结构,它们在两者中都实现了其他不同的方法(因此a有一个额外的方法foo()b还有一个方法bar())。虽然ab会实现相同的界面,但它们不会相同,您也不会期望或想要它们。

当您询问是否a1 == a2时,您收到的是真的,因为a1a2只是同一结构的单独实例。引用我上面链接的帖子,a1a2 相等,但不共享相同的身份。

最后,当你询问是否a1 == a1时,你问的是同一个对象的相同实例是否等于它自己,当然这是真的。在这种情况下,a1a1共享平等和身份。

答案 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编译器优化。