TIL: Go loops and closures
2021-11-08 00:00:00 +0000 UTCI have been working on a toy message queueing server and wrote this code to run a small stress test:
func requestWorker(id int) {
...
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
requestWorker(i)
}()
}
wg.Wait()
}
requestWorker(i)
sends a high number of requests to the server with each request body including the id
passed as a parameter. Here it is the index variable from the loop. However, every request body was sent with an id
equal to 10!
According to this discussion from Stack overflow, this happens because in my initial code the i
variable is only the index variable from the loop, and is being passed by reference because the anonymous function creates a closure.
Passing it as a parameter to the anonymous function instead allocates a new instance for that function call. I had to modify the code to instead say:
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) { // changed this line to include a parameter for the anonymous function
defer wg.Done()
requestWorker(id) // changed this line to use that parameter
}(i) // changed this line to pass the current loop index as a parameter
}
wg.Wait()
}