项目中,需要循环调用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:
如果您觉得我的文章对您有帮助,请关注我的微信公众号,谢谢!