一尘不染

使用for循环进行并发,匿名函数的行为异常

go

我已经找到了一种使代码按我希望的方式运行的方法,但是我想了解为什么它如此运行,以便提高对Go并发性的理解。

我正在测试sync.WaitGroup以等待一些goroutine完成,因为我计划以这种方式多次上传到Amazon S3。

这是我最初的代码:

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

取而代之的是这样的:2, 4, 1, 5, 3

由于循环甚至没有达到6,这对我来说毫无意义。后来我将该i变量作为参数传递给匿名函数,然后按预期运行。

为什么会这样?我不明白


阅读 228

收藏
2020-07-02

共1个答案

一尘不染

常见问题解答对此进行了介绍:以goroutines运行的闭包会发生什么?

在这种情况下,在for循环完成之前,不会对任何goroutine进行调度。为了使for循环中断,i不得小于或等于5,因此在该点为6。当goroutine运行时,它们各自打印i在闭包中捕获的单个变量的值。

当您将i参数作为参数传递给函数时,会将当前值复制到新变量中,并在该时刻捕获该值。

2020-07-02