go闭包
for j := 0; j < 3; j++ {
// 错误:闭包引用共享的 j
go func() {
fmt.Println(j)
}()
}
time.Sleep(100ms) // 等协程执行完
预期输出:0、1、2实际输出:大概率是 3、3、3(因为循环结束后 j=3,协程才执行)。
三、传 j 的副本((j))为什么能解决问题?
代码中 go func(idx int) { ... }(j) 的关键是:
匿名函数定义了参数 idx int;
启动协程时,立刻将当前循环的 j 值作为实参传给 idx(相当于 “快照”);
idx 是每个协程独立的局部变量,不再依赖外部的循环变量 j。
for j := 0; j < 3; j++ {
// 正确:将 j 的当前值传给 idx(副本)
go func(idx int) {
fmt.Println(idx)
}(j)
}
time.Sleep(100ms)
实际输出:0、1、2(顺序可能乱,但值正确)。
浙公网安备 33010602011771号