項目中,需要循環調用API服務器列表,在循環中使用go func創建協程時遇到了參數失靈的現象.
具體代碼如下所示:
for _, apiServerAddr := range apiServerAddrList {
go func() {
callApiServer(apiServerAddr)
}()
}
在運行過程中,發現callApiServer中參數apiServerAddr實際值一直是apiServerAddrList 的最后一個元素值.
將代碼修改為如下形式,則每一個創建的協程中apiServerAddr 則是循環的數值.
for _, apiServerAddr := range apiServerAddrList {
go callApiServer(apiServerAddr)
}
查詢stackoverflow,發現原因如下:
- 循環中,
go callApiServer(apiServerAddr)創建的協程中,使用的apiServerAddr是其數值; - 循環中,
go func(){callApiServer(apiServerAddr)}()創建的協程中,使用的apiServerAddr是其引用,在循環執行至一定次數后,Golang調度器調度協程,協程獲取當前時刻apiServerAddr的數值,此時就會產生錯誤.
golang的閉包,能夠從創建它的作用域中獲取變量,且獲取的是變量的引用而非變量的副本.
go func修改為如下格式,能夠正確調用:
for _, apiServerAddr := range apiServerAddrList {
go func(addr string) {
callApiServer(addr )
}(apiServerAddr )
}
PS:
如果您覺得我的文章對您有幫助,請關注我的微信公眾號,謝謝!

