Given this short program:
package main
import "fmt"
type Foo struct {
doer func()
}
func (f Foo) SetDoer(doer func()) {
f.doer = doer
}
func main() {
foo := Foo{func() { fmt.Println("original") }}
foo.doer()
foo.SetDoer(func() { fmt.Println("replacement") })
foo.doer()
}
The output is:
original
original
I had expected it to be:
original
replacement
Why isn't it? Note that the output is as expected if I set foo.doer
directly in main()
. Just not if I use the SetDoer
method.
In Go, the item on the left of the function name is the receiving type. This is the type from which a function can be called. However, receiver can be both pointers or value types. In this case, it is a value. The receiver is purely for the purpose of organization, under the covers, it is passed to the function like any other argument. You're passing by value so a copy of foo
is passed into SetDoer
, the value is modified, then the setter returns, the value goes out of scope and in the calling scope you're working with the original.
Try this;
// make the receiver a pointer
func (f *Foo) SetDoer(doer func()) {
f.doer = doer
}
// instantiate as pointer
foo := &Foo{func() { fmt.Println("original") }}
foo.SetDoer(func() { fmt.Println("replacement") })
// now the version of doer on foo has been updated.
playground example; https://play.golang.org/p/ZQlvKiluu3