Goroutines in Go
In this tutorial, we are going to discuss Goroutines, a unique feature of the Go programming language that enables easy and efficient handling of concurrent activities. Concurrency in Go is achieved using Goroutines and Channels. However, we will focus solely on Goroutines in this article.
What are Goroutines?
Goroutines can be defined as functions or methods that run concurrently with other functions or methods. They are lightweight threads, managed by Go runtime rather than the operating system. The advantage of Goroutines is that they allow us to perform multiple tasks at the same time, increasing the efficiency and performance of our program.
go function_name()
To create a Goroutine, we use the keyword go
followed by a function call. The control does not wait for the Goroutine to finish, instead, it moves on to the next line, making Goroutines non-blocking.
Simple Goroutine Example
Let's start with a very basic example:
package main
import (
"fmt"
"time"
)
func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
go hello()
time.Sleep(1 * time.Second)
fmt.Println("main function")
}
In the above program, we have two functions: hello
and main
. The main
function starts a new Goroutine by using the go
keyword followed by the hello
function call. After that, it waits for 1 second and prints main function
. The hello
Goroutine prints Hello world goroutine
.
How Goroutines Work?
Goroutines are multiplexed into small number of OS threads. When a new Goroutine is started, the Go runtime checks if there is a current OS thread available. If there is, it will use it; if not, it will create a new one.
One important feature of Goroutines is their size. A Goroutine has a small stack size which grows and shrinks according to the need. This makes Goroutines lightweight and more manageable than threads.
Synchronization using Channels
In our previous example, we used time.Sleep
to wait for the Goroutine to finish before exiting the program. However, this is not an ideal solution. Go provides a better mechanism for synchronization, known as Channels. Channels allow Goroutines to communicate with each other and synchronize their execution.
Here is an example:
package main
import (
"fmt"
)
func hello(done chan bool) {
fmt.Println("Hello world goroutine")
done <- true
}
func main() {
done := make(chan bool)
go hello(done)
<-done
fmt.Println("main function")
}
In the above code, we create a channel done
using the make
function. We pass this channel to the hello
Goroutine. Inside the hello
Goroutine, after printing Hello world goroutine
, we send a true
signal to the done
channel. In the main
function, we receive from the done
channel. This line of code is blocking, which means the main
function will wait until it receives from the done
channel to proceed any further.
Conclusion
Goroutines are one of the most powerful features of Go. They are lightweight, and easy to create and manage. They allow us to write concurrent programs with ease and improve the performance of our applications. To properly synchronize the execution of Goroutines, we use Channels. Remember that Goroutines are not threads, and they are managed by Go runtime, not the operating system. The understanding of Goroutines is essential to write efficient Go programs. Happy coding!