我正在学习 Go 并试图了解它的并发特性。


我有以下程序。


package main


import (

    "fmt"

    "sync"

)


func main() {

    var wg sync.WaitGroup


    for i := 0; i < 5; i++ {

        wg.Add(1)


        x := i


        go func() {

            defer wg.Done()

            fmt.Println(x)

        }()


    }


    wg.Wait()

    fmt.Println("Done")

}

执行时我得到:


4

0

1

3

2

这正是我想要的。但是,如果我对其稍作修改:


package main


import (

    "fmt"

    "sync"

)


func main() {

    var wg sync.WaitGroup


    for i := 0; i < 5; i++ {

        wg.Add(1)


        go func() {

            defer wg.Done()

            fmt.Println(i)

        }()


    }


    wg.Wait()

    fmt.Println("Done")

}

我得到的是:


5

5

5

5

5

我不太明白其中的区别。谁能帮助解释这里发生了什么以及 Go 运行时如何执行此代码?