doudanma9706 2016-08-29 13:33 采纳率: 100%
浏览 221
已采纳

Golang如何在goroutine之间共享变量?

I'm learning Go and trying to understand its concurrency features.

I have the following program.

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")
}

When executed I got:

4
0
1
3
2

It's just what I want. However, if I make slight modification to it:

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")
}

What I got will be:

5
5
5
5
5

I don't quite understand the difference. Can anyone help to explain what happened here and how Go runtime execute this code?

  • 写回答

3条回答 默认 最新

  • doubu1964 2016-08-29 13:45
    关注

    You have new variable on each run of x := i,
    This code shows difference well, by printing the address of x inside goroutine:
    The Go Playground:

    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")
    }
    

    output:

    0xc0420301e0
    0xc042030200
    0xc0420301e8
    0xc0420301f0
    0xc0420301f8
    Done
    

    And build your second example with go build -race and run it:
    You will see: WARNING: DATA RACE


    And this will be fine The Go Playground:

    //go build -race
    package main
    
    import (
        "fmt"
        "sync"
    )
    
    func main() {
        var wg sync.WaitGroup
        for i := 0; i < 5; i++ {
            wg.Add(1)
            go func(i int) {
                defer wg.Done()
                fmt.Println(i)
            }(i)
        }
        wg.Wait()
        fmt.Println("Done")
    }
    

    output:

    0
    4
    1
    2
    3
    Done
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料