I had the following code as part of a test:
expected := 10
var wg sync.WaitGroup
for i := 0; i < expected; i++ {
go func(wg *sync.WaitGroup) {
wg.Add(1)
defer wg.Done()
// do something
}(&wg)
}
wg.Wait()
To my surprise, I got panic: Fail in goroutine after TestReadWrite has completed
when running "go test". When running with "go test -race", I did not get a panic, but the test failed at a later point. In both cases, despite having a wg.Wait(), a goroutine did not finish executing.
I made the following change, and now the test works as expected:
expected := 10
var wg sync.WaitGroup
wg.Add(expected)
for i := 0; i < expected; i++ {
go func(wg *sync.WaitGroup) {
defer wg.Done()
// do something
}(&wg)
}
wg.Wait()
My doubts are:
- A lot of the code I have seen so far does
wg.Add(1)
inside the goroutine. Why does it behave unexpectedly in this specific case? What seems to be happening here is that some goroutines seem to finish running, and get past the wg.Wait(), before other goroutines even start to run. Is using wg.Add(1) inside the goroutine dangerous / to be avoided? If this is not a problem in general, what exactly is causing the problem here? - Is adding
wg.Add(expected)
the correct way to address this problem?