为什么这些golang指针不相等?

时间:2017-01-25 21:52:20

标签: pointers go

在下面的例子中,我检查两个指针​​的相等性

  • 指针指向同一地址
  • 它们不是同一个指针

如何检查两个指针​​是否指向同一个地址?我想要检查两个指针​​的内容是否相等。

package main

import (
    "fmt"
)

type Map struct {}
type Fragment struct {
    Map *Map
}

func (m1 Map) NewFragment() (f Fragment) {
    f.Map = &m1
    return
}


var m Map = Map {}

func main() {
    f := m.NewFragment()
    fmt.Println(f.Map == &m) // false
    fmt.Println(*f.Map == m) // true

}

Go Playground

2 个答案:

答案 0 :(得分:6)

正如JimB回答的那样,您可以使用==来比较指针。此程序以这种方式运行的原因是因为当您调用NewFragment方法时,会复制接收器。在这种情况下,这意味着行f.Map = &m1正在获取副本的地址,而不是原始对象。因此,指针不同(f.Map != &m),值相同(*f.Map == m)。

答案 1 :(得分:4)

指针比较

  

相等运算符==和!=适用于可比较的操作数。   指针值具有可比性。如果两个指针值指向同一个变量,或者两者的值都为nil,则它们相等。

这是一个有效的代码:

func main() {
    s := struct{}{}
    p1 := &s
    p2 := &s
    fmt.Println(p1 == p2)
    fmt.Printf("%p, %p", p1, p2)
}

指针接收器

您的代码存在重大错误,实际上会导致您所描述的行为。可以使用值接收器 func (s SomeObj) DoSomething(){}指针接收器 func (s *SomeObj) DoSomething(){}声明方法。如果使用值接收器声明的方法(就像你所做的那样),你将获得该对象的副本,但如果你使用指针接收器声明一个方法(就像你应该这样),你将获得一个指向该对象本身的指针。

您的代码只缺少一个星号:

type Map struct{}
type Fragment struct {
    Map *Map
}

func (m1 *Map) NewFragment() (f Fragment) { // Note, this is a pointer receiver
    f.Map = m1
    return
}

var m Map = Map{}

func main() {
    f := m.NewFragment()
    fmt.Println(f.Map == &m) // true
    fmt.Println(*f.Map == m) // true
    fmt.Printf("%p, %p", f.Map, &m)
}

结论

指针比较是检查它是否是相同的指针(标识)。因此,如果您仔细查看代码,您会看到上面的代码和我的示例具有相同的含义。

Playgounds:

https://play.golang.org/p/GgTOEgvWA9

https://play.golang.org/p/kFxpu-8TDT