指数超出范围goroutine golang

slo*_*dog 3 go goroutine

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

这是我正在执行的代码.问题是索引超出范围错误是在对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())
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 8

i确实变成了2,但只是在循环的最后.但是因为你的goroutine函数关闭了i,它没有看到igoroutine启动时的值,而是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)
Run Code Online (Sandbox Code Playgroud)