Sorry for the confusing question title, but here's something I don't understand. In the following code, an error is reached when we attempt to assign x
to p
, because x
requires p
to implement M()
, and it doesn't, as M()
has a pointer receiver.
type Person struct {
Name string
Age int
}
func (p *Person) M() {
}
type I interface {
M()
}
func main() {
var x I
var p := Person{}
x = p // Error, M() has pointer receiver
}
That makes relative sense to me. The thing I don't understand is how it's perfectly happy assigning x
to &p
in the following example. In this example, M()
has a value receiver, not a pointer receiver, but it still works just fine.
type Person struct {
Name string
Age int
}
func (p Person) M() {
}
type I interface {
M()
}
func main() {
var x I
var p := Person{}
x = &p // No error
}
This makes no sense to me. A method either implements a value receiver or a pointer receiver, so if it doesn't allow you to assign an interface variable to a value of a type that only implements a pointer receiver, why would it allow you to assign it to a pointer, when the method is only defined as a value receiver?
Lastly, this is further confused by the fact that you can do the following without issue in Go:
func (p *Person) rename(string newName) {
p.Name = newName
}
func main() {
p := Person{Name: "Old name"}
fmt.Println(p.Name)
p.rename("New name")
fmt.Println(p.Name) // Name has changed, despite p not being pointer
}
In the Go tour, it says calls like this are explicitly cast, (eg p.rename("New name")
implicitly becomes (&p).rename("New name")
and pointers become values if needed).
This seems really inconsistent. Am I wrong here?