項目中,需要循環調用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:
如果您覺得我的文章對您有幫助,請關注我的微信公眾號,謝謝!