Loops go vet-func literal捕获的循环变量

Loops go vet-func literal捕获的循环变量,loops,go,concurrency,goroutine,Loops,Go,Concurrency,Goroutine,在以下代码中: package main import "fmt" func main() { for i := 0; i <= 9; i++ { go func() { fmt.Println(i) }() } } 上述程序不提供任何输出 1) 在10个go例程中,它们是针对单个内存位置i的数据竞争吗 2) 为什么上面的代码不打印自由变量的值i 是否存在数据竞赛 是,通过运行go run-race examp

在以下代码中:

package main

import "fmt"

func main() {
    for i := 0; i <= 9; i++ {
        go func() {
            fmt.Println(i)
        }()
    }
}

上述程序不提供任何输出

1) 在10个go例程中,它们是针对单个内存位置
i
的数据竞争吗

2) 为什么上面的代码不打印自由变量的值
i

是否存在数据竞赛

是,通过运行
go run-race example.go
进行确认。主goroutine写入
i
,其他goroutine读取它而不进行任何同步。看见和

为什么上面的代码不打印任何内容

因为当主goroutine结束时,您的程序也会结束。它不会等待其他非
main
goroutine完成。看

修理 制作循环变量的副本,并在闭包中使用该变量,然后使用
sync.WaitGroup
等待启动的goroutine结束:

var wg sync.WaitGroup
for i := 0; i <= 9; i++ {
    i2 := i
    wg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Println(i2)
    }()
}
wg.Wait()
另一种方法是将
i
作为参数传递给启动的函数:

var wg sync.WaitGroup
for i := 0; i <= 9; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done()
        fmt.Println(i)
    }(i)
}
wg.Wait()
var wg sync.WaitGroup

对于i:=0;i如何
添加
完成
访问
wg
以原子方式递增和递减?每走一步-routine@overexchange检查他们的来源。他们使用的是
sync/atomic
包,如果在for循环语句之后在
main()
中说
runtime.Gosched()
,会发生什么?不要使用
wg
@过度交换任何东西
runtime.Gosched()
不是同步工具,它(可能)只是帮助调度器。如果没有正确的同步,您无法保证goroutine的执行顺序。常见问题解答中也介绍了这一点:
9
0
2
1
6
5
3
7
8
4
var wg sync.WaitGroup
for i := 0; i <= 9; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done()
        fmt.Println(i)
    }(i)
}
wg.Wait()