在下面的代码中:
package main
import "fmt"
func main() {
for i := 0; i <= 9; i++ {
go func() {
fmt.Println(i)
}()
}
}
输出:
code$
code$ go install github.com/myhub/cs61a
code$ bin/cs61a
code$
上述程序不提供任何输出。
1) 他们是 10 个 go-routines 中单个内存位置i
的数据竞赛吗?
2)为什么上面的代码不打印自由变量i
的值?
有数据竞赛吗?
是的,通过运行go run -race example.go
进行确认。主 goroutine 写入i
,其他 goroutine 在没有任何同步的情况下读取它。请参阅将参数传递给函数闭包;为什么这两个循环变体会给我不同的行为?并使用循环切片/地图的范围注册多个路线。
为什么上面的代码不打印任何东西?
因为当主程序结束时,您的程序也会结束。它不会等待其他非main
goroutines 完成。请参阅goroutine没有输出
修复
复制循环变量,并在闭包中使用它,并使用sync.WaitGroup
等待启动的goroutines结束:
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()
这将输出(在Go Playground上尝试):
9
0
2
1
6
5
3
7
8
4
另一种方法是将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()
在Go Playground上试试这个。