How to synchronize goroutines in Go using channels

Go is a statically typed language that is famous for its concurrency support. It uses goroutines to run multiple threads in parallel, allowing the computer to perform multiple computations simultaneously. However, when multiple goroutines are running in parallel and accessing shared resources at the same time, ensuring stability in the read and write operations on that particular data becomes an issue. To address this issue, we have channels in Go that enable goroutines to communicate with each other, providing a sophisticated solution to race conditions in Go.

Syntax

To create a channel in Go, use the following syntax:

ch := make(chan type)

Channels in Go are created using the make() function, which takes the type of the value that will be sent over the channel as an argument.

Example

Let’s take an example of two functions, printOne() and printTwo(), running in parallel in different goroutines. The printOne() function prints 1 once after waiting for 10 seconds. The printTwo() function prints 2 twice, with the second 2 being printed after 1 is printed. We’ll use channels to make the goroutines communicate with each other.

package main
import (
"fmt"
"time"
"sync"
)
func printOne(ch chan bool, wg *sync.WaitGroup) {
defer wg.Done()
timeout := 20 * time.Second
// Wait for the specified timeout duration or until a value is received on the channel
select {
case <-time.After(timeout):
fmt.Println("1")
ch <- true // Send a true value on the channel
}
}
func printTwo(ch chan bool, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("2")
check := <-ch // Receive a value from the channel
if check {
fmt.Println("2")
}
}
func main() {
fmt.Println("Process Started!")
var wg sync.WaitGroup
wg.Add(2)
ch := make(chan bool)
// Launch goroutines to execute printTwo and printOne functions concurrently
go printTwo(ch, &wg)
go printOne(ch, &wg)
wg.Wait() // Wait for both goroutines to complete
fmt.Println("Process Ended!")
}
Concurrent execution and synchronization between two goroutines in Go

Code explanation

  • Lines 9–17: The printOne() function takes a channel and a WaitGroup instance as input. It waits for 10 seconds and then prints 1. After 1 has been printed, it puts a true value in the channel.

    Note: In Go, a wait group is a synchronization mechanism used to wait for a collection of goroutines to complete their execution before proceeding further. It allows us to coordinate and control the concurrent execution of goroutines.

  • Lines 19–26: The printTwo() function takes a channel and a WaitGroup instance as input. It prints 2 and then waits for the channel to give a TRUE value. When it gets TRUE from the channel, it prints the second 2.

  • Lines 30–31: We initialize an instance of WaitGroup and add 2 to the instance.

  • Line 32: We create a channel that will carry a value of type bool.

  • Lines 33–34: We run the two functions in separate goroutines.

  • Line 35: We block the main() function until all the goroutines are terminated.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved