当执行以下代码时,我会得到第一个循环完成时的期望值(从0到9的顺序)。但是,当第二个循环结束时,结果却不是我期望的(我期望的结果与第一个循环相同,但它只显示“ 10”):
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
fmt.Println(j)
}(i)
}
wg.Wait()
fmt.Println("done first")
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(i)
}()
}
wg.Wait()
fmt.Println("done second")
}
输出:
0
1
2
3
4
5
6
7
8
9
done first
10
10
10
10
10
10
10
10
10
10
done second
为什么第二个循环不打印序列?
因为第一个每次都会获得循环计数器的副本。而第二个则将变量捕获为闭包的一部分。
首先,在循环的每次迭代中将其传递给这里:
go func(j int) {
defer wg.Done()
fmt.Println(j)
}(i) // <------------ its passed in here as part of each loop iteration
第二个计数器什么也不接收..因此,循环计数器i
被捕获为闭包的一部分。到第一次执行例程执行时,for
循环已完成。循环完成将i
变量(现在是闭包的一部分)设置为10。执行例行程序#1并打印i
..的值,该值现在已经是10,其余的都照做。
TLDR:这里的问题是循环在计划任何go例程运行之前就已经完成了-循环是如此之快。因此,i == 10
当go例程运行时。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句