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

huangapple go评论84阅读模式
英文:

Why are these golang pointers not equal?

问题

在下面的示例中,我检查了两个指针的相等性:

  • 这两个指针指向相同的地址
  • 它们不是同一个指针

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

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

英文:

In the example below I check the equality of two pointers

  • The pointers are pointing to the same address
  • They are not the same pointer

How do I check if two pointers are pointing to the same address? I do not want to check if the contents of both pointers are equal.

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

答案1

得分: 6

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

英文:

As JimB answered, you can use == to compare pointers. The reason this program behaves that way is because when you call the NewFragment method, a copy is made of the receiver. In this case, that means the line f.Map = &m1 is taking the address of the copy, not the original object. Therefore, the pointers are different (f.Map != &m), and the values are the same (*f.Map == m).

答案2

得分: 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) { // 注意,这是一个指针接收器
    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)
}

结论

指针比较是检查是否为相同指针(身份)的操作。因此,如果你仔细观察你的代码,你会发现你的代码和我上面给出的示例具有相同的含义。

Playgrounds:

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

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

英文:

Pointers comparison

> The equality operators == and != apply to operands that are comparable.
> Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil.

This is a valid code:

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

Pointer receivers

Your code has a significant mistake which actually caused the behavior you described. Method could be declared with value receiver func (s SomeObj) DoSomething(){} and with pointer receiver func (s *SomeObj) DoSomething(){}. If a method declared with value receiver (like you did) you will obtain a copy of the object but if you declare a method with pointer receiver (like you should do) you will obtain a pointer to the object itself.

Your code lacks only one asterisk:

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)
}

Conclusion

Pointer comparison is check whether it is the same pointer (identity). So if you look closer at your code you will see that your code and my example located above have the same meaning.

Playgounds:

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

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

huangapple
  • 本文由 发表于 2017年1月26日 05:52:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/41862323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定