有人可以帮助我了解以下关于 golang 循环范围和临时函数的惊喜的“为什么”方面吗?以下是一些更复杂的代码的摘录:
package main
import ( "fmt" )
type Caller struct {
call func()
}
func printer(val int) {
fmt.Printf("the value is %v\n", val)
}
func main () {
values := []int{1,2,3}
var callers []Caller
for _,val := range values {
call := func() { printer(val) }
callers = append(callers, Caller{call})
}
for _, caller := range callers {
caller.call()
}
}
这产生了(对我来说)令人惊讶的结果:
the value is 3
the value is 3
the value is 3
如果我通过将范围值循环体更改为此代码来更改该代码:
theVal := val
call := func() { printer(theVal) }
callers = append(callers, Caller{call})
然后我们得到了最初希望的结果:
the value is 1
the value is 2
the value is 3
从根本上说,一个有效,另一个无效——我很清楚这一点,可以试着记住这个成语。我希望有更多的理解,也许是 golang 的一点生活课。范围规则和延迟执行是什么意思,这意味着循环变量保持最终的有效值并提交到循环期间构建的每个临时函数?为什么值“val”没有放入动态构建的函数“调用”中?我怀疑我对一些基本的东西感到困惑。即使看到一个工作版本,我也不确定我将来能否避免这样的陷阱。如果您对“为什么”迭代值会有这样的行为有建议,我很想听听(并提前感谢您)。
慕桂英3389331
相关分类