1. 程式人生 > >Golang 閉包

Golang 閉包

為了加速資料處理,往往我們會選擇goroutines並行處理。

values := []string{"c++", "golang", "python"}
for _, val := range values {
    go func() {
        fmt.Println(val)
    }()
}

執行的結果是

python
python
python

和預期不符,為什麼?

for 迴圈使用的變數val接受 slice 中的每個元素,由於整個閉包都繫結到val上,很可能當goroutines還沒開始執行,for 迴圈就結束了,所以val是最後一個值。

通過將ival作為引數傳入閉包可以解決這個問題。

方式一:

for _, val := range values {
    go func(val string) {
        fmt.Println(val)
    }(val)
}

方式二:

for i, _ := range values {
    go func(i int) {
        fmt.Println(values[i])
    }(i)
}

在迴圈體內宣告的變數不在迭代之間共享,也可以解決上面的問題。

方式三:

for i, _ := range
values { val := values[i] go func() { fmt.Println(val) }() }

for 迴圈遍歷也可以得到預期結果。

方式四:

for i := 0; i < len(values); i++ {
    func() {
        fmt.Println(values[i])
    }()
}

參考

https://github.com/golang/go/wiki/CommonMistakes