It’s been a year since my last live stream, as I was moving across the globe.
I’m finally settled (enough) to start up again.
Join me, as I’ll begin building a new feature in my open-source project. The next session will be August 15, at 19:00 UTC. Subscribe on YouTube and hit the Notify me button so you don’t miss it!
Yesterday we wrote some Go code to wait for goroutines using a channel:
done := make(chan struct{})
for i := range 10 {
go func(i int) {
fmt.Println(i)
done <- struct{}{} // Signal that this goroutine is done
}(i)
}
// Wait for all goroutines to finish
for range 10 {
<-done
}
Today we’re going to modify this code to use sync.WaitGroup
, which is a more idiomatic way to wait for multiple goroutines in Go.
The sync
package provides a number of synchronization primitives. We’ll be looking specifically at the WaitGroup
type for now, which provides three* methods:
- Add(int): Increments the WaitGroup counter by the specified (possibly negative) number.
- Done(): Decrements the WaitGroup counter by one. Equivalent to calling
Add(-1)
. - Wait(): Blocks until the WaitGroup counter is zero.
*Go 1.25 will add a fourth, which we’ll discuss separately in the future.
Let’s update our code to use sync.WaitGroup
:
wg := &sync.WaitGroup{}
for i := range 10 {
wg.Add(1)
go func(i int) {
fmt.Println(i)
wg.Done() // Signal that this goroutine is done
}(i)
}
// Wait for all goroutines to finish
wg.Wait()
This code operates virtually identically to the previous version, but it’s arguably a bit more readable. You no longer have to manage a channel directly, and instead just increment and decrement the WaitGroup
counter as goroutines start and finish. Then finally, we wait for all goroutines to finish by calling wg.Wait()
.
In the coming days we’ll explore some more advanced features of sync.WaitGroup
.