Golang循环中调用go func参数异常分析

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

posted @ 2019-04-30 15:25  从此寂静无声  阅读(4348)  评论(4编辑  收藏  举报