This question already has an answer here:
Been reading about it a lot, but the dichotomy between Pointer receiver and Value receiver still confuses me.
Let's say we have this...
type Apple struct {
color string
}
func (a *Apple) Eat() {
fmt.Printf("Eating %s apple
", a.color)
}
func main() {
a := Apple{"red"}
a.Eat()
}
I would think that this is an error as we are trying to call a method with Pointer receiver via a value (a
is value). But this compiles and runs and prints.
My understanding is that if a
was a pointer, then it would work for both value receiver and pointer receiver methods. But when a
is a value, then it should only work with methods that have value receivers, as pointer receiver methods are NOT in the method set.
But the above seems to contradict this. What's going on. (I am running Go 1.8.3
).
https://play.golang.org/p/eWkDHwIgOZ
-- Update --
Turns out there are two things to be aware of.
First is the actual rule, and second is the compiler aid we get in using these receivers.
The rule is that a pointer receiver method can NOT be called via value -- it has to be a pointer. But when we call a.Eat
(a
being a value) -- the compiler does its helping hand and turns a
into &a
. The rule is still enforced - albeit "behind the scene".
The rule asserts itself in interfaces though.
Let's say we have an interface...
type Edible interface {
Eat()
}
// Note that this is not a method, it is a simple function.
func EatMore(x Edible) {
fmt.Println("Eating more...")
x.Eat()
}
func main() {
a := Apple{"red"}
a.Eat() // Okay -- because compiler is helping
EatMore(a) // Wrong -- the rule asserts, compiler does not help
}
Here, within the call to EatMore(a)
, the compiler does not turn a
into &a
-- and hence we get the error. The correct way would be, as expected, EatMore(&a)
.
Hence, it is important to distinguish between the rule from the help Go compiler offers us in "forgetting" about this rule -- especially in method call expressions.
https://play.golang.org/p/p3-LUlbmCg
</div>