When attempting to coordinate the completion of multiple goroutines using sync.WaitGroup, one may encounter the error "fatal error: all goroutines are asleep - deadlock!" This cryptic message can be puzzling, especially when the code appears to be written according to the documentation examples.
The source of this error lies in the way Go handles values passed to functions. When passing a sync.WaitGroup object directly, Go creates a copy of that value, essentially passing a different object to each goroutine. This creates a disconnect between the original WaitGroup and the copies that the goroutines operate on.
The solution to this issue is to pass a pointer to the sync.WaitGroup instead. By doing so, all goroutines will reference the same underlying object and operate on its internal counters consistently. The correct code using a pointer is provided below:
import "sync" func doWork(wg *sync.WaitGroup) error { defer wg.Done() // Do some heavy lifting... request URL's or similar return nil } func main() { wg := &sync.WaitGroup{} // Use pointer to pass the WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go doWork(wg) } }
With this alteration, the goroutines will properly interact with the WaitGroup object, incrementing its counter before starting their work and decrementing it upon completion. As a result, the WaitGroup.Wait() call in the main function will not block indefinitely and the program will execute as expected.
The above is the detailed content of Why Does Using `sync.WaitGroup` Lead to 'fatal error: all goroutines are asleep - deadlock!', and How Can I Fix It?. For more information, please follow other related articles on the PHP Chinese website!