Join me this Friday, August 15, at 3:00pm EDT (19:00 UTC), for a live stream where I’ll be building a new feature in my open-source project. Subscribe on YouTube and hit the Notify me button so you don’t miss it!
One thing we can do with sync.WaitGroup
, that may not be immediately obvious, is to call Add
from within a goroutine that’s managed by the wait group itself:
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
user := fetchUser()
}()
wg.Add(1)
go func() {
defer wg.Done()
orders := fetchOrders()
for _, order := range orders {
wg.Add(1)
go func(order Order) {
defer wg.Done()
processOrder(order)
}(order)
}
}()
wg.Wait()
In this code, we attempt to fetch a user, and the user’s orders, concurrently, each in a separate goroutine. Then, for each order, we spawn another goroutine to process that order—all managed by the same wait group.
The important thing in such a case is that wg.Wait()
is called only after the first wg.Add()
call has been made, and that every other wg.Add()
is called before the waitgroup counter reaches zero. This is most easily done by ensuring you call wg.Add()
before calling wg.Done()
in the goroutine itself, as shown above.
And finally, of course, ensure that the wg.Done()
calls match the wg.Add()
calls, so that the wait group counter reaches zero when all goroutines are done.