我已经找到了一种使代码按我希望的方式运行的方法,但是我想了解为什么它如此运行,以便提高对Go并发性的理解。
我正在测试sync.WaitGroup以等待一些goroutine完成,因为我计划以这种方式多次上传到Amazon S3。
sync.WaitGroup
这是我最初的代码:
func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go func() { fmt.Println(i) time.Sleep(time.Second * 1) wg.Done() }() } wg.Wait() }
我很惊讶地看到输出是:6, 6, 6, 6, 6。
6, 6, 6, 6, 6
取而代之的是这样的:2, 4, 1, 5, 3。
2, 4, 1, 5, 3
由于循环甚至没有达到6,这对我来说毫无意义。后来我将该i变量作为参数传递给匿名函数,然后按预期运行。
i
为什么会这样?我不明白
常见问题解答对此进行了介绍:以goroutines运行的闭包会发生什么?
在这种情况下,在for循环完成之前,不会对任何goroutine进行调度。为了使for循环中断,i不得小于或等于5,因此在该点为6。当goroutine运行时,它们各自打印i在闭包中捕获的单个变量的值。
当您将i参数作为参数传递给函数时,会将当前值复制到新变量中,并在该时刻捕获该值。