转到:将var转换为匿名函数

我在将变量传输到匿名函数时遇到麻烦。有解决方案吗?


import  "github.com/lxn/walk"


***


var openAction [12]*walk.Action

for i := 0; i < 12; i++ {


    openBmp, err := walk.NewBitmapFromFile(_films[i][0])

    if err != nil {

        log.Printf("Open bitmap for buildBody() :%v\n", err)

    }

    openAction[i] = walk.NewAction()

    openAction[i].SetImage(openBmp)

    openAction[i].SetText(_films[i][2])

    openAction[i].Triggered().Attach( func(){

        exec(i)

    })

    mw.ToolBar().Actions().Add(openAction[i])

}

exec(i)我总是= 11


aluckdog
浏览 212回答 3
3回答

忽然笑

我认为这将为您提供所需的东西:openAction[i].Triggered().Attach(func(x int) func() {&nbsp; &nbsp; return func() { exec(x) }}(i))诀窍是让您的匿名函数返回一个匿名函数,并且每个创建的函数都将包围i的每个值。

幕布斯7119047

for i := 0; i < 12; i++ {&nbsp; &nbsp; i := i&nbsp; &nbsp; ...看起来很疯狂,这是您会在Go代码中看到的东西。它是由闭包的工作方式和变量的作用域产生的。您的匿名函数是一个捕获i的闭包。具体来说,它捕获的是一个名为i的变量,而不是i的当前值,并且它捕获范围内的任何i。在您的原始代码中,这是循环变量,对于循环的每次迭代,它都是相同的变量。您所有的闭包都捕获了相同的变量。增加的会i := i在每次迭代中声明一个新变量。现在,每个闭包都将捕获此新变量,并且在每次迭代中它将是一个不同的变量。更详细地讲,循环变量i的范围是for语句。这包括循环块,但是由于循环变量i的声明不在该块之外,因此在块内声明一个具有相同名称的新变量是合法的,并在该点处创建一个新变量。然后,将循环变量阴影化。通常,这样声明的变量会放在堆栈上,但是在这种情况下,编译器转义分析发现,当闭包超出范围的末尾时,您的闭包仍在引用此块变量,因此该变量被放置在堆。在每次迭代中,将重新输入该块,并在堆上放置一个新变量i。

芜湖不芜

您正在遇到go's for循环的怪癖。循环中的i变量不是每次迭代的新变量。因此,您所有的闭包都关闭在其值在其下更改的同一变量上。当您的代码在循环后运行时,所有函数的关闭值i都为11。解决方案是将i传递给一个函数,然后该函数返回另一个关闭函数arg的函数。这就是Adam Crosslands解决方案起作用的原因。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go