A short excerpt from the Tour of Go states that:
Methods with pointer receivers can modify the value to which the
receiver points [...]. Since methods often need to modify their
receiver, pointer receivers are more common than value receivers.
Why is r.b
shown correctly while r.a
is not modified at all?
As already stated in my answer below, your add()
method is a value receiver. Therefore, it will take your initialized struct (i.e. r
), copy it and then modify it accordingly. Because you have initialized a new map under r.b
in your main()
function, here only the reference to this map is copied but not the whole map. Therefore, the manipulation on the map works but not on the slice r.a
. But why does r.a
not change at all? That's because append()
, which is located in the add()
method, stores a new slice header under your a
property, and is pointing to a different section of the underlying array. At the end, your value receiver method add()
made a copy of r
, set a new slice header under the property a
, and never changed the original struct r
, that has been defined in the main()
function as it was copied through the value receiver method add()
.
In your case the add()
method is a so called value receiver method that cannot do any manipulation on your defined struct r
located in the main()
function directly, but copies it and does the manipulation afterwards. Therefore, you need to turn your add()
method into a pointer receiver method just like this:
func (r *R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
Now the method is taking the actual reference of your struct r
, that is initiated in the main()
function, and modifies it accordingly.
How could it work without changing your add()
method to a pointer receiver?
You simply would have to return the copied struct in your add()
method like this:
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
fmt.Println(r.add()) // outputs {[2] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() R {
r.a = append(r.a, 2)
r.b[2] = 2
return r
}