Почему функция Go Function Field Setter не сохраняет эту функцию?
Учитывая эту короткую программу:
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()
}
Вывод:
original
original
Я ожидал, что это будет:
original
replacement
Почему бы и нет? Заметьте, что результат будет таким, как и ожидалось, если я установлю foo.doer
непосредственно в main()
. Только не в том случае, если я использую метод SetDoer
.
1 ответ:
В Go элемент слева от имени функции является типом приема. Это тип, из которого может быть вызвана функция. Однако приемником могут быть как указатели, так и типы значений. В данном случае это ценность. Приемник служит исключительно для целей организации, под прикрытием, он передается функции, как и любой другой аргумент. Вы проходите мимо значения, поэтому копия
foo
передается вSetDoer
, значение изменяется, затем возвращается сеттер, значение выходит за пределы области и в вызывая scope, вы работаете с оригиналом.Попробуйте это;
// 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.
Пример игровой площадки; https://play.golang.org/p/ZQlvKiluu3