I'm trying to test a method. Its signature is func (gv *myType) Update(all map[string][]SomeType) error
Although the test fails (the expected value doesn't match the received value) I've found that also the map it receives(allSub
) is "updated" after the method is evaluated. Here is the code:
t.Logf("allsub %v", allSub)
if err := gv.Update(allSub); err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(egv, gv) {
t.Errorf("allSub %v", allSub)
return
}
The output
mth_test.go:265: allsub map[b:[{1 3 3}] a:[{1 0 0} {1 2 0}]]
mth_test.go:271: allSub map[a:[{1 2 0}]]
As you can see on t.Logf("allsub %v", allSub)
we have map[b:[{1 3 3}] a:[{1 0 0} {1 2 0}]]
and then after the evaluation if !reflect.DeepEqual(egv, gv)
allSub becomes allSub map[a:[{1 2 0}]]
. This drives me crazy and I'm wondering how is this possible? allSub is not a pointer.
Map, slice, channels are reference types. The spec is in-process to become clearer about this but basically the implementation of these builtin types entails a reference to an underlying data structure.
So you can consider that an object of type map
is actually a reference to an associative array.
Effective Go has a little paragraph on it : https://golang.org/doc/effective_go.html#maps
I quote :
Like slices, maps hold references to an underlying data structure. If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller.