Goroutines
A goroutine is a function executing concurrently with other goroutines in the same address space. Goroutines are much lighter than OS threads: the initial stack takes only a few kilobytes, and the Go scheduler distributes thousands of goroutines across a small number of system threads.
Starting a goroutine
Just put the go keyword before a function call:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 3; i++ {
fmt.Println(s, i)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go say("goroutine")
say("main")
}
When main returns, the program exits without waiting
for other goroutines. That is why you wait using
channels or sync.WaitGroup,
not time.Sleep.
Anonymous functions
for i := 0; i < 3; i++ {
go func(n int) {
fmt.Println("worker", n)
}(i)
}
Since Go 1.22 the loop variable is created anew on each iteration,
so the closure go func() { fmt.Println(i) }() works correctly too.
The G-M-P model
- G (goroutine) — a goroutine;
- M (machine) — an OS thread;
- P (processor) — a logical processor with a goroutine run queue.
Their number is set by
GOMAXPROCS(the number of CPU cores by default).
Tips
- Always know when and how a goroutine will exit — otherwise you get a leak.
- Use
context.Contextto cancel long-running operations. - Run tests with the
-raceflag to detect data races.