Using WaitGroup in Golang
Last Updated :
12 Jul, 2025
Go routines are a great selling point for golang, making it a choice of a lots of developers out there. In this post we will see a common problem with these goroutines and try to solve it.
Let's see a simple code snippet illustrating this problem,
Go
package main
import "fmt"
func runner1() {
fmt.Print("\nI am first runner")
}
func runner2() {
fmt.Print("\nI am second runner")
}
func execute() {
go runner1()
go runner2()
}
func main() {
// Launching both the runners
execute()
}
As you just saw there was nothing in the output, this because as soon as you launch both the goroutines, your main function just got terminated. And every program in Golang executes until main function is not terminated. So, what can we do with this problem
1. We can wait for some time after launching the runners, for this purpose we will use "time" packages function "Sleep" which pauses the execution of function for given duration,
Go
package main
import (
"fmt"
"time"
)
func runner1() {
fmt.Print("\nI am first runner")
}
func runner2() {
fmt.Print("\nI am second runner")
}
func execute() {
go runner1()
go runner2()
}
func main() {
// Launching both the runners
execute()
time.Sleep(time.Second)
}
Output:
I am second runner
I am first runner
We just solve the problem, after launching our runners we wait for a second, so our main function was sleeping(blocked) for 1 sec. In that duration all of the go routines were executed successfully. But Golang is a fast language, It doesn't take 1 sec to just print 2 strings.
The problem is that, our executors executes in bit amount of time so we unnecessarily blocking the program for 1 sec. In this example it doesn't seems to be a critical problem but if you making a production grade server who is going to serve 1000's of request concurrently this will be a big problem.
2. Let's use another Golang's standard library primitive "sync.WaitGroup". WaitGroup is actually a type of counter which blocks the execution of function (or might say A goroutine) until its internal counter become 0.
How It Works ?
WaitGroup exports 3 methods.
1 | Add(int) | It increases WaitGroup counter by given integer value. |
2 | Done() | It decreases WaitGroup counter by 1, we will use it to indicate termination of a goroutine. |
3 | Wait() | It Blocks the execution until it's internal counter becomes 0. |
Note: WaitGroup is concurrency safe, so its safe to pass pointer to it as argument for Groutines.
Go
package main
import (
"fmt"
"sync"
)
func runner1(wg *sync.WaitGroup) {
defer wg.Done() // This decreases counter by 1
fmt.Print("\nI am first runner")
}
func runner2(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Print("\nI am second runner")
}
func execute() {
wg := new(sync.WaitGroup)
wg.Add(2)
// We are increasing the counter by 2
// because we have 2 goroutines
go runner1(wg)
go runner2(wg)
// This Blocks the execution
// until its counter become 0
wg.Wait()
}
func main() {
// Launching both the runners
execute()
}
Output:
I am second runner
I am first runner
The output is same but we out program doesn't block for 1 sec . Pattern, we showed you above is a common practice in writing concurrent code in Golang.
Similar Reads
Structures in Golang A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct. This concept is generally compared with the classes in object-orient
7 min read
How to Split a String in Golang? In Go language, strings differ from other languages like Java, C++, and Python. A string in Go is a sequence of variable-width characters, with each character represented by one or more bytes using UTF-8 encoding. In Go, you can split a string into a slice using several functions provided in the str
3 min read
Inheritance in GoLang Inheritance means inheriting the properties of the superclass into the base class and is one of the most important concepts in Object-Oriented Programming. Since Golang does not support classes, so inheritance takes place through struct embedding. We cannot directly extend structs but rather use a c
3 min read
Nested Structure in Golang A structure or struct in Golang is a user-defined type, which allows us to create a group of elements of different types into a single unit. Any real-world entity which has some set of properties or fields can be represented as a struct. Go language allows nested structure. A structure which is the
3 min read
Pointer to a Struct in Golang In Go, structs are used to create custom data types that group different fields together. When working with structs, using pointers can be especially beneficial for managing memory efficiently and for avoiding unnecessary copying of data. A pointer to a struct allows you to directly reference and mo
3 min read
Multiple Interfaces in Golang In Go language, the interface is a collection of method signatures and it is also a type means you can create a variable of an interface type. In Go language, you are allowed to create multiple interfaces in your program with the help of the given syntax: type interface_name interface{ // Method sig
4 min read