3 回答
TA贡献1806条经验 获得超5个赞
我认为这将为您提供所需的东西:
openAction[i].Triggered().Attach(func(x int) func() {
return func() { exec(x) }
}(i))
诀窍是让您的匿名函数返回一个匿名函数,并且每个创建的函数都将包围i的每个值。
TA贡献1794条经验 获得超8个赞
for i := 0; i < 12; i++ {
i := i
...
看起来很疯狂,这是您会在Go代码中看到的东西。它是由闭包的工作方式和变量的作用域产生的。您的匿名函数是一个捕获i的闭包。具体来说,它捕获的是一个名为i的变量,而不是i的当前值,并且它捕获范围内的任何i。在您的原始代码中,这是循环变量,对于循环的每次迭代,它都是相同的变量。您所有的闭包都捕获了相同的变量。增加的会i := i在每次迭代中声明一个新变量。现在,每个闭包都将捕获此新变量,并且在每次迭代中它将是一个不同的变量。
更详细地讲,循环变量i的范围是for语句。这包括循环块,但是由于循环变量i的声明不在该块之外,因此在块内声明一个具有相同名称的新变量是合法的,并在该点处创建一个新变量。然后,将循环变量阴影化。通常,这样声明的变量会放在堆栈上,但是在这种情况下,编译器转义分析发现,当闭包超出范围的末尾时,您的闭包仍在引用此块变量,因此该变量被放置在堆。在每次迭代中,将重新输入该块,并在堆上放置一个新变量i。
TA贡献1796条经验 获得超7个赞
您正在遇到go's for循环的怪癖。循环中的i变量不是每次迭代的新变量。因此,您所有的闭包都关闭在其值在其下更改的同一变量上。当您的代码在循环后运行时,所有函数的关闭值i都为11。
解决方案是将i传递给一个函数,然后该函数返回另一个关闭函数arg的函数。这就是Adam Crosslands解决方案起作用的原因。
- 3 回答
- 0 关注
- 211 浏览
添加回答
举报