Table of contents
- Goroutines
- 1.1. Goroutine Lifecycle
- 1.2. Program Termination
- 1.3. Summary
I. Goroutines
Goroutines are lightweight threads managed by the Go runtime. Each one is a function that runs concurrently with the other in the same address space.
Key Characteristics
- Lightweight: Only 2KB of stack space initially
- Growable: Stack grows and shrinks as needed
- Multiplexed: Many goroutines run on few OS threads
- Cheap: Creating millions is feasible
Let’s tweak Rob Pike’s famous example:
package main
import (
"fmt"
"time"
)
func boring(msg string) {
for i := 0; ; i++ {
fmt.Printf("%s %d\n", msg, i)
time.Sleep(time.Second)
}
}
func main() {
go boring("boring!")
fmt.Println("I'm listening.")
time.Sleep(2 * time.Second)
fmt.Println("You're boring; I'm leaving.")
}
Console Output:
23:21:26 I'm listening.
23:21:26 boring 0
23:21:27 boring 1
23:21:28 You're boring; I'm leaving.
What happens when running this program:
- main() start (goroutine 0)
- go boring(“boring!”) creates goroutine 1
- main prints “I’m listening.” and both goroutines run concurrently
- Main sleeps for 2 seconds
- While main is sleeping, goroutine 1 (boring) print boring 0
- While main is sleeping, goroutine 1 (boring) print boring 1
- Main prints “You’re boring; I’m leaving.” after sleeps 2 seconds
- Main exits, terminating the entire program
1.1. Goroutine Lifecycle
- Created - goroutine is spawned
- Running - actively executing
- Sleeping - time.Sleep() or waiting
- Terminated - function returns
1.2. Program Termination
Critical Point: When main() returns, the entire program exits, even if other goroutines are still running.
1.3. Summary
- Goroutines are lightweight and cheap
- Use go keyword to launch them
- They run concurrently, not in sequence
- Program exits when main() returns
- Perfect for I/O-bound tasks