What is Go concurrency?

Key takeaways:

  • Concurrency allows multiple tasks to be performed simultaneously, enhancing efficiency and performance in applications.

  • Go utilizes goroutines and channels to implement concurrency.

  • Goroutines allow functions to run concurrently, initiated with the go keyword.

  • Channels enable safe communication and synchronization between goroutines.

  • Mastering concurrency in Go boosts performance and helps tackle complex software challenges effectively.

Nowadays, the ability to efficiently manage multiple tasks simultaneously is more important than ever. Imagine building applications that can handle thousands of requests at once, just like how major platforms such as Netflix manage their streaming services.

This is where concurrency comes into play.

What is concurrency?

Concurrency means to perform multiple tasks at the same time. In simpler words, when working and progressing with more tasks simultaneously is known as concurrency.

In the Go language, we can use concurrency using goroutines and channels. Let's now explore both the goroutines and channels in detail.

Goroutines

Functions that can run concurrently with other functions are known as goroutines. A goroutine can be created using the go keyword.

go myfunc()

Goroutines code example

Let's now look at the working of a goroutine using a coding example.

package main
import (
"fmt"
"time"
)
func myfunc(str string) {
for i := 0; i < 3; i++ {
time.Sleep(10 * time.Millisecond)
fmt.Println(str)
}
}
func main() {
go myfunc("learn")
myfunc("create")
}

Explanation

  • Lines 8–13: This function, named myfunc, takes a string argument str and prints it three times with a short delay between each print. It uses a for loop and the time.Sleep function to introduce a delay of 10 milliseconds between each print.

  • Line 16: This line starts a new goroutine by using the go keyword before calling the myfunc function with the argument "learn".

  • Line 17: This line calls the myfunc function with the argument "create" in the main goroutine. The key point here is that the go myfunc("learn") line launches a goroutine, and myfunc("create") continues executing in the main goroutine without waiting for the goroutine to complete. As a result, "create" and "learn" will be printed concurrently, and the order of the output may vary each time you run the program due to the concurrent execution of goroutines.

Let's now learn about channels in Go.

Channels

Channels in Go serve as typed conduits for sending and receiving values using the channel operator, <-.

You can use the channel operator in the following ways:

  • chl <- x: Sends the value x to the channel chl.

  • x := <-chl: Receives a value from the channel chl and assigns it to the variable x.

The direction of the arrow indicates the flow of data.

Similar to maps and slices, channels must be created before being utilized:

chl := make(chan int)

By default, sending and receiving operations on channels block until the other side is ready. This inherent behavior enables goroutines to synchronize without requiring explicit locks or condition variables.

The following program sums the numbers in a slice by distributing the computational work between two goroutines. The final result is calculated once both goroutines have completed their respective computations.

Goroutines with channel code example

package main
import "fmt"
func score(n []int, ch chan int) {
score := 0
for _, i := range n {
score += i
}
ch <- score // send score to c
}
func main() {
slice := []int{3, 2, 6, -9, 4, 0}
ch := make(chan int)
go score(slice[:len(slice)/2], ch)
go score(slice[len(slice)/2:], ch)
a, b := <-ch, <-ch // receive from c
fmt.Println(a, b, a+b)
}

Explanation

  • Lines 5–11: This function, score, takes a slice of integers n and a channel of integers ch as parameters. It iterates through the elements of the slice, calculating the sum of all the numbers. The calculated score is sent to the channel ch using ch <- score.

  • Lines 13–22: The main function starts by creating a slice of integers named slice. It then creates a channel of integers, ch, using make(chan int). Two goroutines are launched concurrently using the go keyword. Each goroutine calculates the sum of a different half of the slice and sends the result to the channel ch. The main goroutine receives the two results from the channel ch using the expressions a, b := <-ch, <-ch. Finally, it prints the received values and their score using fmt.Println(a, b, a+b).

In summary, this code demonstrates using goroutines and channels in Go to concurrently calculate the sums of two halves of a slice of integers. The main goroutine then receives these results from the channel, prints them, and displays their sum. Using channels ensures synchronization and proper communication between the concurrently running goroutines.

Conclusion

Incorporating concurrency in the programming toolkit, especially with Go's goroutines and channels, can significantly improve the performance and responsiveness of the applications. By allowing multiple tasks to run simultaneously and enabling seamless communication between them, we can tackle complex problems more efficiently.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


Can a goroutine return a value?

Goroutines cannot directly return values; instead, they typically send results back through channels.


What is a select statement in Go?

In Go, the select statement is a language construct used for working with multiple channel operations concurrently. It allows a Go program to wait for communication on multiple channels simultaneously and execute code based on the first channel operation that becomes available. The select statement is similar to the switch statement, but it deals with communication actions on channels, such as sending or receiving data.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved