索引超出范围错误,在其中似乎无法通过for循环生成的goroutine
这是我正在执行的代码。
问题是在goroutine中对countlinks调用的参数之一的求值内会产生索引范围错误。我们要针对的 slice 的长度始终为2。根据我对go中for循环的理解,i
永远不应求值为2(表达式grph.entryPoints[i]
中的屈服索引超出范围),但事实并非如此。请告诉我我疯了。
func main() {
grph := structures.ConfigGraphDefault()
counter := structures.NewCounter()
queue := structures.NewQueue()
tracker := structures.NewTracker()
fmt.Printf("entries: %v\nnodes: %v\n", grph.EntryPoints, grph.Nodes)
wg := sync.WaitGroup{}
fmt.Println(len(grph.EntryPoints))
// this will always evaluate to 2
l := len(grph.EntryPoints)
for i := 0; i < l; i++ {
wg.Add(1)
go func() {
fmt.Printf("index: %v, length of slice: %v\n", i, len(grph.EntryPoints))
structures.CountLinks(&grph, counter, queue, tracker, grph.EntryPoints[i], i)
wg.Done()
}()
}
wg.Wait()
fmt.Printf("counter: %v", counter.GetCounts())
}
最佳答案
i
确实变为2,但仅在循环的最后。但是,由于您的goroutine函数关闭了i
,因此在启动goroutine时看不到i
的值,而是执行时的i
的值。换句话说,您所有的goroutine共享相同的变量i
。
要解决此问题,一种方法是将i
复制到在循环体内声明的帮助程序变量。更好的方法是将其作为参数传递给goroutine:
go func(i int) {
fmt.Printf("index: %v, length of slice: %v\n", i, len(grph.EntryPoints))
structures.CountLinks(&grph, counter, queue, tracker, grph.EntryPoints[i], i)
wg.Done()
}(i)