我不确定"func literal"是什么,所以这个错误让我有点困惑.我想我看到了这个问题——我从一个新的go routine 中引用了一个范围值变量,因此该值可能会随时发生变化,而不是我们所期望的.解决这个问题的最好方法是什么?

有问题的代码:

func (l *Loader) StartAsynchronous() []LoaderProcess {
    for _, currentProcess := range l.processes {
        cmd := exec.Command(currentProcess.Command, currentProcess.Arguments...)
        log.LogMessage("Asynchronously executing LoaderProcess: %+v", currentProcess)
        go func() {
            output, err := cmd.CombinedOutput()
            if err != nil {
                log.LogMessage("LoaderProcess exited with error status: %+v\n %v", currentProcess, err.Error())
            } else {
                log.LogMessage("LoaderProcess exited successfully: %+v", currentProcess)
                currentProcess.Log.LogMessage(string(output))
            }
            time.Sleep(time.Second * TIME_BETWEEN_SUCCESSIVE_ITERATIONS)
        }()
    }
    return l.processes
}

我建议的解决办法是:

func (l *Loader) StartAsynchronous() []LoaderProcess {
    for _, currentProcess := range l.processes {
        cmd := exec.Command(currentProcess.Command, currentProcess.Arguments...)
        log.LogMessage("Asynchronously executing LoaderProcess: %+v", currentProcess)
        localProcess := currentProcess
        go func() {
            output, err := cmd.CombinedOutput()
            if err != nil {
                log.LogMessage("LoaderProcess exited with error status: %+v\n %v", localProcess, err.Error())
            } else {
                log.LogMessage("LoaderProcess exited successfully: %+v", localProcess)
                localProcess.Log.LogMessage(string(output))
            }
            time.Sleep(time.Second * TIME_BETWEEN_SUCCESSIVE_ITERATIONS)
        }()
    }
    return l.processes
} 

但这真的能解决问题吗?我刚刚将引用从Range变量移动到另一个局部变量,该变量的值基于我所在的for each循环的迭代.

推荐答案

别难过,这是围棋新手经常犯的错误,是的,每个循环的变量currentProcess都会改变,所以您的goroutines将使用片l.processes中的最后一个进程,您所要做的就是将变量作为参数传递给匿名函数,如下所示:

func (l *Loader) StartAsynchronous() []LoaderProcess {

    for ix := range l.processes {

        go func(currentProcess *LoaderProcess) {

            cmd := exec.Command(currentProcess.Command, currentProcess.Arguments...)
            log.LogMessage("Asynchronously executing LoaderProcess: %+v", currentProcess)

            output, err := cmd.CombinedOutput()
            if err != nil {
                log.LogMessage("LoaderProcess exited with error status: %+v\n %v", currentProcess, err.Error())
            } else {
                log.LogMessage("LoaderProcess exited successfully: %+v", currentProcess)
                currentProcess.Log.LogMessage(string(output))
            }

            time.Sleep(time.Second * TIME_BETWEEN_SUCCESSIVE_ITERATIONS)

        }(&l.processes[ix]) // passing the current process using index

    }

    return l.processes
}

Go相关问答推荐

golang-jWT签名无效

如何在gofr发起的服务间调用请求中添加Authorization Header?

无法使用Segentio;S Kafka-Go连接到融合的Kafka

运行 Docker 容器 - X11 无法打开显示:0

如何为ANTLR4目标Go调试监听器

如何将整数哈希细分为范围

GRPC 元数据未在 Go 中更新

为什么 reflect.TypeOf(new(Encoder)).Elem() != reflect.TypeOf(interfaceVariable)?

GqlGen - 在字段解析器中访问查询输入参数

使用无服务器工作流 go sdk 时出现间歇性 JSON 解组错误

转到文本/模板模板:如何根据模板本身的值数组判断值?

将接口方法的参数限制为几个允许的 struct ?

Go AST:获取所有 struct

如何使用golang操作很长的字符串以避免内存不足

如何在golang中使用ozzo验证进行时间最大验证

Go:如何创建一个可以提供配置文件中描述的 url 的服务器

使用 LoadLibraryA(path_to_dll) 加载 DLL 会将文件描述符 0、1 和 2 的继承句柄标志 (HANDLE_FLAG_INHERIT) 从 1 更改为 0

如何在 Go 中使用 Pact 返回错误请求(400、500)?

如何从 docker-compose 命令运行 2 个不同的命令:

如何从应用程序调用谷歌云身份 API