Index out of range error where it seems impossible in goroutine generated by for loop
This is the go code I am executing.
The problem is that an index out of range error is yielded inside the evaluation of one of the arguments to countlinks call in a goroutine. The length of the slice we're iterating against is ALWAYS 2. Based on my understanding of for loops in go, i
should never evaluate to 2 (yielding index out of range in expression grph.entryPoints[i]
), and yet it is. Please, tell me how I am crazy.
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
does become 2, but only at the very end of the loop. But because your goroutine function closes over i
, it doesn't see the value of i
at the time the goroutine was started, but the value of i
at the time it executes. In other words, all your goroutines share the same variable i
.
To fix this, one way is to copy i
to a helper variable declared inside the loop body. A nicer way is to pass it as an argument to the 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With