英文:
Why Doesn't a Go Function Field Setter Retain the Function?
问题
给定这个简短的程序:
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
为什么会这样?请注意,如果我直接在main()
函数中设置foo.doer
,输出结果是符合预期的。只是在使用SetDoer
方法时不符合预期。
英文:
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.
答案1
得分: 5
在Go语言中,函数名左侧的项目是接收类型。这是可以调用函数的类型。然而,接收器可以是指针类型或值类型。在这种情况下,它是一个值类型。接收器纯粹是为了组织的目的,在底层,它像任何其他参数一样传递给函数。你通过值传递,所以foo
的副本被传递给SetDoer
,该值被修改,然后setter返回,该值超出作用域,在调用作用域中你正在使用原始值。
尝试这样做:
// 将接收器设为指针类型
func (f *Foo) SetDoer(doer func()) {
f.doer = doer
}
// 实例化为指针类型
foo := &Foo{func() { fmt.Println("original") }}
foo.SetDoer(func() { fmt.Println("replacement") })
// 现在foo上的doer版本已经更新。
playground示例:https://play.golang.org/p/ZQlvKiluu3
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论