3 回答
TA贡献1829条经验 获得超13个赞
您的函数文字i从外部范围引用。如果您请求 的值i,您将获得当前的任何值i。为了使用iGo 例程创建时的值,请提供一个参数:
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(i int) {
fmt.Println(i)
wg.Done()
}(i)
}
wg.Wait()
}
TA贡献1810条经验 获得超4个赞
该变量i未在函数字面量中声明,因此它成为闭包的一部分。理解闭包的一个简单方法是考虑如何实现它们。简单的解决方案是使用指针。你可以认为函数字面量被编译器改写成一些
func f123(i *int) {
fmt.Println(*i)
wg.Done
}
在调用此函数时,通过 go 语句,将
i
变量的地址传递给被调用的 f123(编译器生成的示例名称)。您可能正在使用默认的 GOMAXPROCS==1,因此 for 循环在没有任何调度的情况下执行 5 次,因为该循环没有 I/O 或其他“调度点”,例如通道操作。
当循环以 结束时
i == 5
,wg.Wait
finally 会触发五个准备运行的 goroutines(对于 f123)的执行。他们当然都有指向同一个整数变量的相同指针i
。现在每个 goroutine 都看到相同的
i
值 5。
当 GOMAXPROCS > 1 运行时,或者当循环产生控制时,您可能会得到不同的输出。这也可以通过例如runtime.Gosched来完成。
- 3 回答
- 0 关注
- 189 浏览
添加回答
举报