【问题标题】:Why are these golang pointers not equal?为什么这些 golang 指针不相等?
【发布时间】:2026-02-10 13:55:01
【问题描述】:

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

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

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

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

【问题讨论】:

  • 在您的代码中,func (m1 Map) NewFragment 对值而不是指针进行操作。如果将其更改为 func (m1 *Map) NewFragment() 等,则两个 Println 都将返回 true。我不确定您希望该程序如何工作。
  • 使用==。如果指针指向同一个变量,则它们具有相同的地址。来自规范:Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil.

标签: pointers go


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    指针比较

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

    这是一个有效的代码:

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

    指针接收器

    您的代码有一个严重错误,实际上导致了您描述的行为。方法可以用 value receiver func (s SomeObj) DoSomething(){}pointer receiver 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)
    }
    

    结论

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

    游乐场:

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

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

    【讨论】: