Goroutines are concurrent operations that can be executed regardless of the function in which they are running. The main feature of goroutines is that they can be executed in parallel. That is, on multi-core architectures, it is possible to execute separate goroutines on separate cores of the processor, thus the goroutines will be executed in parallel, and the program will complete faster.
Each goroutine typically represents a function call, and executes all of its instructions sequentially. When we run a program on Go, we've already We work with at least one goroutine, which is represented by the main function. This function sequentially executes all the instructions that are defined within it.
To determine the goroutines, the go statement is used, which is placed before the function call:
go fuction_call
For example, let's define several goroutines that print Hello World a number of times:
package main
import (
"fmt"
)
func main() {
for i := 1; i < 7; i++ {
go printHelloWorldNTimes(i)
}
fmt.Println("Done!")
}
func printHelloWorldNTimes(n int) {
if n < 1 {
fmt.Println("Invalid input number")
return
}
for i := 0; i < n; i++ {
fmt.Println(n, "- Hello World")
}
}
However, instead of six Hello World on the console, when we call the program, we can only see the line "Done!":
Done!
Why is this happening? Once called, go printHelloWorldNTimes(i)
the main function starts the goroutine, which begins executing in its context, regardless of the main function. That is, in fact, main and printHelloWorldNTimes are executed in parallel.
However, the main goroutine is the main function call. And if the execution of this function ends, then the execution of the entire program ends. Since calls to the printHelloWorldNTimes function represent goroutines, the main function does not wait for them to complete and continues executing after they start. Some goroutines may be completed before the main function, and accordingly, we will be able to see their result on the console. However, a situation may arise that the main function will be executed before the calls to the factorial function. Therefore, we may not see Hello World on the console.
To still see the result of the goroutine execution, we put at the end of the main function a call to a function fmt.Scanln()
that expects user input from the console:
package main
import (
"fmt"
)
func main() {
for i := 1; i < 7; i++ {
go printHelloWorldNTimes(i)
}
fmt.Scanln()
fmt.Println("Done!")
}
func printHelloWorldNTimes(n int) {
if n < 1 {
fmt.Println("Invalid input number")
return
}
for i := 0; i < n; i++ {
fmt.Println(n, "- Hello World")
}
}
And we get the result:
3 - Hello World
3 - Hello World
3 - Hello World
4 - Hello World
4 - Hello World
4 - Hello World
4 - Hello World
1 - Hello World
2 - Hello World
2 - Hello World
Done!
It is worth noting that since each goroutine runs in its context and executes independently and in parallel compared to other goroutines, in this case, it is not possible to determine which goroutine will complete first.