Go Ranged Loop 范围和间接函数

有人可以帮助我了解以下关于 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”没有放入动态构建的函数“调用”中?我怀疑我对一些基本的东西感到困惑。即使看到一个工作版本,我也不确定我将来能否避免这样的陷阱。如果您对“为什么”迭代值会有这样的行为有建议,我很想听听(并提前感谢您)。


一只甜甜圈
浏览 101回答 1
1回答

慕桂英3389331

这也适用于你。这是来自FAQ的链接。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 {        var call func()        func(v int) {            call = func() {                printer(v)            }        }(val)        callers = append(callers, Caller{call})    }    for _, caller := range callers {        caller.call()    }}另一种方法是将 val 的当前值绑定到每个闭包启动时,您可以将其存储在一个新变量中,然后使用它(您为解决它所做的方法)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go