在下面的代码中。
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) 单个内存位置是否存在数据竞赛?i
中的10个执行程序?
2) 为什么上面的代码没有打印自由变量的值?i
?
是否存在数据竞赛?
是的,通过运行 go run -race example.go
. 主goroutine写道 i
,而其他goroutines读取它时不需要任何同步。参见 将参数传递给函数闭合; 为什么这两个for循环的变化会给我不同的行为? 和 使用循环slicesmap的范围注册多个路由。.
为什么上面的代码没有任何打印?
因为当主程序结束时,你的程序也结束了。它不会等待其他非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()
这将输出(在 去游乐场):
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()
试试这个 去游乐场.