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条)

报告相同问题?

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上