Charles Holbrow
Charles Holbrow

Reputation: 4231

Why are these golang pointers not equal?

In the example below I check the equality of two pointers

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

Upvotes: 0

Views: 4224

Answers (2)

I159
I159

Reputation: 31139

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

Upvotes: 4

Logiraptor
Logiraptor

Reputation: 1518

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

Upvotes: 6

Related Questions