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