有人可以帮助我了解以下关于 golang 循环范围和临时函数的惊喜的“为什么”方面吗?以下是一些更复杂的代码的摘录:package mainimport ( "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 3the value is 3the value is 3如果我通过将范围值循环体更改为此代码来更改该代码: theVal := val call := func() { printer(theVal) } callers = append(callers, Caller{call})然后我们得到了最初希望的结果:the value is 1the value is 2the value is 3从根本上说,一个有效,另一个无效——我很清楚这一点,可以试着记住这个成语。我希望有更多的理解,也许是 golang 的一点生活课。范围规则和延迟执行是什么意思,这意味着循环变量保持最终的有效值并提交到循环期间构建的每个临时函数?为什么值“val”没有放入动态构建的函数“调用”中?我怀疑我对一些基本的东西感到困惑。即使看到一个工作版本,我也不确定我将来能否避免这样的陷阱。如果您对“为什么”迭代值会有这样的行为有建议,我很想听听(并提前感谢您)。
1 回答
慕桂英3389331
TA贡献2036条经验 获得超8个赞
这也适用于你。这是来自FAQ的链接。
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 {
var call func()
func(v int) {
call = func() {
printer(v)
}
}(val)
callers = append(callers, Caller{call})
}
for _, caller := range callers {
caller.call()
}
}
另一种方法是将 val 的当前值绑定到每个闭包启动时,您可以将其存储在一个新变量中,然后使用它(您为解决它所做的方法)。
- 1 回答
- 0 关注
- 100 浏览
添加回答
举报
0/150
提交
取消