Golang 高並發編程For循環中使用Goroutine最容易犯的錯誤


file

Golang

goroutine是Go語言強大的特性之一,合理的利用它才能發揮最大的價值

1、經調查

發現初學者一般會犯以下錯誤使用goroutine

func goroutineRun(values []int)  {
    for value := range values {
        go value.test()
    }
}

或者使用閉包調用

func goroutineRun(values []int)  {
    for value := range values {
        go func() {
            fmt.Println(value)
        }()
    }
}

這2段代碼實際上是遍歷數組的所有變量。由於閉包只是綁定到這個value變量上,並沒有被保存到goroutine棧中,所以以上代碼極有可能運行的結構都輸出為切片的最后一個元素。因為這樣寫會導致for循環結束后才執行goroutine多線程操作,這時候value值只指向了最后一個元素。這樣的結果不是我們所希望的,而且還會產生並發的資源搶占沖突所以是非常不推薦這樣寫的。

2、解決方法

goroutine的正確寫法

for val := range values {
    go func(val interface{}) {
        fmt.Println(val)
    }(val)
}

在這里將 val 作為一個參數傳入 goroutine 中,每個 val 都會被獨立計算並保存到 goroutine 的棧中,從而得到預期的結果。

另一種方法是在循環內定義新的變量,由於在循環內定義的變量在循環遍歷的過程中是不共享的,因此也可以達到同樣的效果:

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

公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM