Go:将var传输到匿名函数

Vla*_*lav 5 go

我无法将变量转换为匿名函数.有解决方案吗?

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])
}
Run Code Online (Sandbox Code Playgroud)

exec(i)我总是= 11

Son*_*nia 10

for i := 0; i < 12; i++ {
    i := i
    ...
Run Code Online (Sandbox Code Playgroud)

看起来很疯狂,这是你将在Go代码中看到的东西.它来自闭包的工作方式和变量的作用方式.你的匿名函数是一个捕获我的闭包.具体来说,它捕获一个名为i的变量,而不是i的当前值,它捕获我在范围内的任何内容.在原始代码中,这是循环变量,对于循环的每次迭代,它都是相同的变量.所有闭包都捕获了相同的变量.添加i := i在每次迭代时声明一个新变量.现在每个闭包都将捕获这个新变量,并且在每次迭代时它将是一个不同的变量.

更详细一点,循环变量i的范围是for语句.这包括循环块,但由于循环变量i的声明在块之外,因此在块内声明具有相同名称的新变量是合法的,并在块中的该点创建新变量.然后对循环变量进行阴影处理.通常,这样声明的变量会出现在堆栈中,但在这种情况下,编译器转义分析会发现当块在块的末尾超出范围时,闭包仍然引用此块变量,因此变量放在堆.在每次迭代时,重新输入块,并在堆上放置一个新变量i.


Ada*_*and 6

我想这会得到你想要的东西:

openAction[i].Triggered().Attach(func(x int) func() {
    return func() { exec(x) }
}(i))
Run Code Online (Sandbox Code Playgroud)

诀窍是让你的匿名函数返回一个匿名函数,每个创建的函数将包含i的每个值.