越界错误goroutine golang

4

在for循环生成的goroutine中出现了不可能的索引超出范围错误

这是我正在执行的go代码。 问题在于,在一个goroutine的countlinks调用的参数求值中产生了一个索引超出范围错误。我们正在迭代的切片的长度始终为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())
}
1个回答

10

i最终会变成2,但是只会在循环结束时才会发生。但由于你的goroutine函数闭合了i,它看到的是执行时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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接