英文:
Data passed by reference to "defer"
问题
在《掌握Go并发》一书中有一段文字,让我觉得可能对于 "defer" 函数有所遗漏。
你还应该注意,任何通过引用传递的数据可能处于意外状态。
func main() {
aValue := new(int)
defer fmt.Println(*aValue)
for i := 0; i < 100; i++ {
*aValue++
}
}
这段代码会打印出0,我认为是因为根据规范:
每次执行 "defer" 语句时,函数值和调用的参数会像平常一样被求值并重新保存。
也就是说,当调用 defer 时,*aValue 的值为0,这就是为什么最后打印出0的原因。在这种情况下,是否将指针传递给 defer 函数是无关紧要的。
我的理解正确吗?还是我有所遗漏?
英文:
There is a passage in the "Mastering Concurrency in Go" book which made me think I might be missing something about "defer" functions.
You should also take note that any data passed by reference may be in an unexpected state.
func main() {
aValue := new(int)
defer fmt.Println(*aValue)
for i := 0; i < 100; i++ {
*aValue++
}
}
This prints 0, I thought, because according to spec:
> Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew
That is, *aValue is 0 when defer is called and that's why at the end it prints 0. Whether or not a pointer is passed to the differ function in this case is irrelevant.
Is my understanding correct or am I missing something?
答案1
得分: 3
考虑一个使用结构体的情况。
type User struct {
Name string
}
func main() {
user := User{}
defer fmt.Printf("%#v\n", user)
user.Name = "AJ"
}
你知道defer
应该在最后执行,所以你可能期望看到User{Name: "AJ"}
,但实际上你得到的是User{Name: ""}
,因为defer
绑定了参数。
如果你使用指针,它就能正常工作。
user := &User{}
如果你使用闭包,它也能正常工作。
defer func() {
fmt.Printf("%#v\n", user)
}()
英文:
Consider a situation using structs.
type User struct {
Name string
}
func main() {
user := User{}
defer fmt.Printf("%#v\n", user)
user.Name = "AJ"
}
You know defer
should run at the end, so you might expect to see User{Name: "AJ"}
but instead you get User{Name: ""}
because defer
binds parameters.
If you use a pointer it works.
user := &User{}
If you use a closure, it works.
defer func() {
fmt.Printf("%#v\n", user)
}()
答案2
得分: 2
defer语句是在“评估”参数并保存结果,而在defer调用时,评估*aValue
的结果为0。你可能正在寻找类似这样的代码:
func main() {
aValue := new(int)
defer func() { fmt.Println(*aValue) }()
for i := 0; i < 100; i++ {
*aValue++
}
}
英文:
The defer statement is "evaluating" the parameters and saving the result, and the result of evaluating *aValue
is 0 at the time of the defer call. Something like this may be what you're looking for:
func main() {
aValue := new(int)
defer func() { fmt.Println(*aValue) }()
for i := 0; i < 100; i++ {
*aValue++
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论