問題
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
for i := 0; i < 10; i++ {
wg.Add(1)
go func(){
fmt.Println(i)
defer wg.Done()
}()
}
wg.Wait()
}
[why@localhost] ~/Desktop/go/gin-frame$go run test.go
10
4
10
10
10
10
10
10
10
10
[why@localhost] ~/Desktop/go/gin-frame$
爲什麼不是按照任意順序打印0-9呢?
原因
閉包對捕獲對外部變量並不是以傳值方式訪問對,而是以引用方式訪問。並且,在Go語言中,同一個Goroutine線程內部,順序一致性內存模型是得到保證的,但是在不同的Goroutine之間,並不滿足順序一致性的內存模型,因此我們可以看到不會打印前幾位數,至少一定不會打印0。
解決
閉包函數定義參數,用於爲每個閉包函數生成獨有變量。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int){
fmt.Println(i)
defer wg.Done()
}(i)
}
wg.Wait()
}
[why@localhost] ~/Desktop/go/gin-frame$go run test.go
1
0
9
5
3
2
7
4
6
8
[why@localhost] ~/Desktop/go/gin-frame$