You have no excuses now, use this free credit to launch your projects now on Digital Ocean, you're free to spend it whenever you want within the following 60 days.
Table of contents
Go: introduction to goroutines and concurrency
Go: introduction to goroutines and concurrency
As I mentioned in the introduction to the go programming language: go is a specialized concurrency language . It is a language that was designed to handle multiple tasks asynchronously. This entry is about go channels.
Concurrency is not parallelism
Before we begin, remember that parallelism and concurrency are different. This post is too small to deal with such a broad topic, however there are two resources I want to highlight:
- Concurrent Programming by Felipe Restrepo Street
- Concurrency vs parallelism by Hector Patricio in The dojo blog
I quote a sentence from the first resource that, in my opinion, sums up the difference quite well:
A program is concurrent if it can support two or more actions **in progress.
A program is parallel if it can support two or more actions executing simultaneously.
Felipe Restrepo Calle
If they still seem confusing and you don’t understand the difference, give those posts a read and you should be ready to move on.
Coroutines in go
A coroutine , in go, is a function or method that runs concurrently with other functions or methods. In go, corroutines are referred to as goroutines or goroutines. Even the main function, main, is executed inside one.
Goroutines are used in design patterns, such as the worker-pool-design-pattern
To generate a goroutine we add the keyword go before a function. This will schedule the function for asynchronous execution.
func write(texto string) {
fmt.Println(texto)
}
fmt.Println("hey")
go write("hey again")
// hey
In the above case, due to its asynchronous nature, the goroutine does not stop code execution. This implies that the body of the main function continues its execution and **our goroutine never executes.
But then, how do we get our goroutine to run? The naive approach would be to use a sleep to pause the execution of the code. This, as you know, is nonsense, we can’t be putting sleeps everywhere, the flow of the program would be unnecessarily slowed down!
// Don't
time.Sleep(1 * time.Second)
A better approach would be to create a WaitGroup.
WaitGroups in go
A WaitGroup will stop the execution of the program and wait for the goroutines to be executed.
Internally, a WaitGroup works with a counter, when the counter is at zero the execution of the code will continue, while if the counter is greater than zero, it will wait for the other goroutines to finish executing.
var wg sync.WaitGroup
wg.Wait()
fmt.Println("If waitgroup counter is greater than 0 it will continue the execution.")
And how do we change the counter value?
To increment and decrement the counter of the WaitGroup we will use the Add and Done methods, respectively.
The Add method
The Add method increments the WaitGroup counter by n units, where n is the argument we pass to it.
The trick is to call it every time you run a goroutine.
wg.Add(1)
go write("Hey")
The Done Method
The Done method is responsible for decrementing one unit of the WaitGroup counter. We will call it to tell the WaitGroup that the goroutine has finished and decrement the counter by one.
func write(text string, wg *sync.WaitGroup) {
fmt.Println(text)
wg.Done()
}
Remember that the instance of the WaitGroup (wg *) needs to be passed by reference or else we will not access the original WaitGroup.
func write(text string, wg *sync.WaitGroup) {
fmt.Println(text)
defer wg.Done()
}
Tip: use defer over the Done method to ensure that it is the last thing to be executed.
Once the wg.wait counter becomes zero, program execution continues.
var wg sync.WaitGroup
wg.Add(1)
go writeInChannel("Hello", &wg)
wg.Wait()
Anonymous functions in goroutines
When using goroutines, it is quite common to use anonymous functions to avoid declaring a new function.
go func() {
}()
Remember that the parentheses that appear after the body of the function execute the anonymous function that we declare and also receive its arguments.
go func(text string) {
}("Text")
More resources about goroutines
Finally, here are some other resources on goroutines that you can consult.