项目中,需要循环调用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:

如果您觉得我的文章对您有帮助,请关注我的微信公众号,谢谢!

Golang循环中调用go func参数异常分析的更多相关文章

  1. javascript 循环中调用异步的同步需求

    // 关于Promise:可以直接使用promise Promise.resolve(123).then(v => { console.log(v) }) // 循环中调用异步 let arr ...

  2. golang 反射中调用方法

    反射中调用函数 众所周知,golang中的函数是可以像普通的int.float等类型变量那样作为值的,例如: package main import "fmt" func hell ...

  3. shell下在while循环中使用ssh命令的问题

    1 现象描述 最近使用ssh批量执行命令(已经做了密钥互信了),脚本读取配置文件中的主机列表(内容为每行一台主机IP地址),然后执行,可是每次只是执行第一台,就退出循环了. 2 排查思路 由于脚本比较 ...

  4. spring中for循环中事务

    1.需求:批量插入一批数据,不用spring jdbc的批处理,用for循环插入数据. 2.遇到的问题:在for循环中,当一个插入不成功,前面插入成功的数据也将回滚. 3.初始设计:在service中 ...

  5. 关于由ajax返回的数据在for循环中只能取到最后一个数的问题

    关于由ajax返回的数据在for循环中只能取到最后一个数的问题 以上是来自后台的数据格式.从数据中可以看出,里面包含两个商品,每个商品价格分别为:1.98,13.60.这里我要计算两个商品的总价格,但 ...

  6. 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘

    [C#]无损转换Image为Icon 如题,市面上常见的方法是: var handle = bmp.GetHicon(); //得到图标句柄 return Icon.FromHandle(handle ...

  7. 如何给ioloop.run_sync()中调用的函数传入参数

    问题 如何给tornado.ioloop.IOLoop中的run_sync方法中调用的函数添加参数 解决方案 使用functools.partial 解决示例 from tornado import ...

  8. 使用“2”个参数调用“SetData”时发生异常:“程序集“

    使用"2"个参数调用"SetData"时发生异常:"程序集"Microsoft.VisualStudio.ProjectSystem.VS. ...

  9. 【问题】Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数

    [问题]Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数. [解决]直接对变量加引号,如: <button onclick="deleteProduct('@ ...

随机推荐

  1. openlayers在底图上添加静态icon

    越学习openlayer你会发现openlayer是真的很强大,今天记录一下学习的成果,需求是做那种室内的CAD的场景然后里面展示人员icon并且实时展示人员的位置信息,以及点击弹出对应人员的一些位置 ...

  2. 数据结构——顺序栈(sequence stack)

    /* sequenceStack.c */ /* 栈 先进后出(First In Last Out,FILO)*/ #include <stdio.h> #include <stdl ...

  3. C++中二分法之upper_bound()、lower_bound、binary_search()函数

    前言 数组.容器vector都适用,在头文件"algorithm"中 下面的例子是针对容器的,注意返回的是距离元素3最近的指针it,输出的是*it结果为元素4,假如我想得到位置而非 ...

  4. 使用Django创建RESTful API

    Agenda 1.What is an api Api refers to application programming interface It is a set of subroutine de ...

  5. C#:ref关键字和out关键字的区别

    1.在不使用关键字(比如ref关键字.out关键字等)修饰函数的情况下,大部分函数的参数是以值传递的方式,也就是说,“调用函数”在使用参数(比如myNumber)时,是把该参数复制多一份,然后将其传递 ...

  6. RabbitMQ的构架

    初识rabbitMQ RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现. AMQP :Advanced Message Queue,高级消息队列协议.它是应用层协议的一个开放 ...

  7. git rebase的使用: 合并多次commit记录; rebase一个分支的起点

    合并多次commit记录: good:https://blog.csdn.net/csdlwzy/article/details/83379546 使用 git log 命令查看提交历史: 想要合并前 ...

  8. 线程池 ThreadPoolExecutor 类的源码解析

    线程池 ThreadPoolExecutor 类的源码解析: 1:数据结构的分析: private final BlockingQueue<Runnable> workQueue;  // ...

  9. hbase源码之 compact源码(一)

    hbase compact流程较多,这里分章节介绍,首先介绍compact在regionserver中的调用流程,并不会涉及真正的compact读取合并文件的流程,后续介绍. 在regionserve ...

  10. JS中Map的用法

    声明 var map = new Map(); 设值 map.set("key","value"); 取值 map.get("key"); ...