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

file

Golang

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

一、經調查

發現初學者通常會犯如下錯誤使用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值只指向了最後一個元素。這樣的結果不是咱們所但願的,並且還會產生併發的資源搶佔衝突因此是很是不推薦這樣寫的。併發

二、解決方法

goroutine的正確寫法線程

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

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

另外一種方法是在循環內定義新的變量,因爲在循環內定義的變量在循環遍歷的過程當中是不共享的,所以也能夠達到一樣的效果:blog

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

公衆號

相關文章
相關標籤/搜索