Golang 闭包不存储捕获的变量?

问题描述 投票:0回答:2

在下面的这段代码中,我期望输出为 0, 1, 2, 3,..., 9。但是,只产生输出 10, 10,...,10。

package main

import "fmt"

func adder() []func() {
    out := []func(){}
    for i := 0; i < 10; i++ {
        out = append(out, func() { fmt.Println(i) })
    }

    return out
}

func main() {
    out := adder()
    for i := 0; i < 10; i++ {
        out[i]()
    }
}

我的心理模型表明每次在 for 循环中都会生成并存储一个新函数,但事实似乎并非如此。有没有一种解决方案可以在不修改签名(无参数或全局变量)的情况下生成新函数,但仍保留 i 的当前值?

function go closures return-value
2个回答
9
投票

每次迭代都会创建一个新函数 is,但它们都在同一个变量

i
上结束。该变量会随着每次迭代而更新,直到最后一次,因此当您遍历并执行所有这些函数时,它们都引用相同的
i
,具有相同的值
10

如果您不想要这种行为,则必须关闭循环变量:

for i := 0; i < 10; i++ {
    temp := i
    out = append(out, func() { fmt.Println(temp) })
}

0
投票

此行为在 Go 版本 1.22 中已更改,请查看 发行说明,以及 Playground 上的此示例:https://go.dev/play/p/djpXI9ZqunG

© www.soinside.com 2019 - 2024. All rights reserved.