在for each循环中使用go例程时,func literal捕获go vet range变量
我不确定什么是“func literal”,因此这个错误让我有点困惑。我想我看到了这个问题——我在一个新的go例程中引用了一个范围值变量,因此该值可能随时发生变化,而不是我们所期望的。解决这个问题的最好办法是什么 有关守则:在for each循环中使用go例程时,func literal捕获go vet range变量,go,Go,我不确定什么是“func literal”,因此这个错误让我有点困惑。我想我看到了这个问题——我在一个新的go例程中引用了一个范围值变量,因此该值可能随时发生变化,而不是我们所期望的。解决这个问题的最好办法是什么 有关守则: func (l *Loader) StartAsynchronous() []LoaderProcess { for _, currentProcess := range l.processes { cmd := exec.Command(curre
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
}
但这真的解决了问题吗?我刚刚将引用从范围变量移动到另一个局部变量,该局部变量的值基于我所处的for each循环的迭代。是的,您所做的是正确修复此警告的最简单方法
在修复之前,只有一个变量,所有goroutine都引用它。这意味着他们看不到启动时的值,而是当前值。在大多数情况下,这是该范围内的最后一个进程。别难过,这是围棋新手的常见错误,是的,varcurrentProcess会为每个循环更改,因此您的goroutines将使用slice l中的最后一个进程。进程,您只需将变量作为参数传递给匿名函数,像这样:
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
}
对于那些寻求更简单示例的人: 这是错误的:
func main() {
for i:=0; i<10; i++{
go func(){
processValue(i)
}()
}
}
func processValue(i int){
fmt.Println(i)
}
func main() {
for i:=0; i<10; i++{
go func(differentI int){
processValue(differentI)
}(i)
}
}
func processValue(i int){
fmt.Println(i)
}
func main(){
对于i:=0;i如果您有使用JS中Javascript和闭包的经验,那么很容易将其与for循环中的setTimeout的经典示例进行比较,并在迭代结束时使用循环变量的最终值进行setTimeout。感谢更新后的代码,它看起来很棒!我的代码中有一个非常严重的错误,需要呃,一个小时的修复工作与类似的事情有关。我回来了[]*LoaderProcess之前没有意识到一个片已经是指针,所以我实际上返回了一个片指针,其中每个指针指向同一个LoaderProcess实例,而该实例恰好是最后一个完成的命令。每次执行后都不一样。因此,从一段代码中学到了两个重要的教训。谢谢。我们是否要使用索引发送吗?太棒了,谢谢。您能确认func literal只是一个内嵌定义的函数吗?比如内嵌go例程所需的函数吗?