Consider the following code:
package main
import (
"fmt"
)
type Person struct {
Age int
M map[string]func()
}
func New() Person {
p := Person{1, make(map[string]func())}
p.M["1"] = p.Add
return p
}
func (p *Person) Add() {
fmt.Println("Age before mutating in Add", p.Age)
p.Age += 1 // here age should become 3
fmt.Println("Age after mutating in Add", p.Age)
}
func (p *Person) Run() {
fmt.Println("Age before mutating in Run", p.Age)
p.Age += 1 // here age should be 2
p.M["1"]()
fmt.Println("Age after mutating in Run", p.Age)
}
func main() {
p := New()
fmt.Println("age before", p.Age)
p.Run()
fmt.Println("age after", p.Age)
}
This produces output
age before 1
Age before mutating in Run 1
Age before mutating in Add 1
Age after mutating in Add 2
Age after mutating in Run 2
age after 2
Here M is a map member of a struct, it stores methods of the same struct against strings.
In main we instantiate a non pointer struct value.
Then we call a method Run on that struct which is defined to have a pointer receiver. This should share a pointer to the struct with the method, which should allow the method to mutate the original struct.
Within Run we call the function Add stored within the map, via the map. But this does not mutate the struct, in fact it seems to operate on the state of the object as it was when newly created.
Any changes within Add are lost by the time Run ends, although Add is also declared with a pointer receiver.
I suspect this is because the original object was copied into the map somehow when calling p.M["1"] = p.Add?
Why does calling the method with pointer receiver not mutate the object?
Playground link https://play.golang.org/p/CRer_rT8_sj