Go中閉包的隱含問題

問題

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$

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章