Understanding Golang's `sync.WaitGroup`
James Reed
Infrastructure Engineer · Leapcell

Key Takeaways
sync.WaitGroup
helps synchronize multiple goroutines efficiently.Add
,Done
, andWait
control goroutine execution and completion.- Proper usage prevents race conditions and ensures program stability.
In concurrent programming with Go, managing the synchronization of multiple goroutines is crucial. The sync.WaitGroup
from Go's standard library offers a simple and effective way to wait for a collection of goroutines to finish executing. This article delves into the functionality, usage, and internal workings of sync.WaitGroup
.
What is sync.WaitGroup
?
sync.WaitGroup
is a synchronization primitive that allows a goroutine to wait for a set of operations running in other goroutines to complete. It provides a way to block the execution of a program until all specified goroutines have finished.
Key Methods of sync.WaitGroup
WaitGroup
offers three primary methods:
-
Add(delta int)
: Adjusts the number of goroutines to wait for by the specifieddelta
. A positive value indicates that new goroutines are being added, while a negative value signifies that goroutines have completed. -
Done()
: Decrements the counter by one, indicating that a goroutine has finished its task. This is essentially a shorthand forAdd(-1)
. -
Wait()
: Blocks the execution of the calling goroutine until the counter becomes zero, meaning all goroutines have completed their tasks.
Using sync.WaitGroup
Here's a basic example demonstrating how to use WaitGroup
:
package main import ( "fmt" "sync" ) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d starting\n", id) // Simulate work fmt.Printf("Worker %d done\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go worker(i, &wg) } wg.Wait() }
In this example:
- A
WaitGroup
variablewg
is declared. - The
Add
method increments the counter by one for each goroutine. - Each
worker
function callsDone
upon completion, decrementing the counter. - The
Wait
method blocks the main function until all goroutines have finished.
Internal Mechanism of WaitGroup
Under the hood, WaitGroup
maintains a counter to track the number of active goroutines. The Add
method modifies this counter, while Done
decreases it. The Wait
method blocks until the counter reaches zero. This mechanism ensures that the main goroutine waits for all spawned goroutines to complete before proceeding.
Important Considerations
-
Consistency in
Add
andWait
Calls: Ensure that calls toAdd
andWait
are not executed concurrently. It's recommended to invokeAdd
before starting the goroutine to avoid race conditions. -
Avoid Negative Counter: The counter should not become negative. Each
Add
call should have a correspondingDone
call to maintain balance. -
Reusability: A
WaitGroup
must not be reused after aWait
method has returned unless it is ensured that all previous goroutines have completed and no newAdd
calls are made.
Conclusion
sync.WaitGroup
is a powerful tool in Go's concurrency model, providing a straightforward way to synchronize multiple goroutines. By understanding its methods and proper usage, developers can effectively manage concurrent operations, ensuring that all goroutines complete their tasks before the program proceeds.
FAQs
This will cause a panic as the counter cannot go negative.
Yes, but only if all previous goroutines have completed before adding new ones.
To prevent race conditions and ensure all goroutines are counted correctly.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ