Goroutines are the foundation of every concurrent Go program, from servers to pipelines.
A goroutine is a function running concurrently with the rest of the program. You start one by putting go before a call: go handle(conn). The call returns immediately; the function runs independently.
Goroutines are cheap. Each starts with a small stack (a few kilobytes) that grows as needed, and the Go runtime multiplexes them onto a handful of OS threads. Running thousands — even hundreds of thousands — is normal. A web server typically uses one goroutine per request.
Things to keep in mind:
- When
mainreturns, the program exits, killing any goroutines still running. You must explicitly wait for work you care about, using channels orsync.WaitGroup(coming next). godiscards the function's return values. Results come back through channels or shared, synchronised variables.- Goroutines share memory. If two of them access the same variable and at least one writes, you need synchronisation, or you have a data race.
- Since Go 1.22, loop variables are per-iteration, so
for _, url := range urls { go fetch(url) }and closures capturingurlare safe. In older code you'll seeurl := urlcopies for this reason.
Every goroutine you start should have a clear way to finish. A goroutine blocked forever on a channel nobody will send to is a goroutine leak: it holds its memory until the process exits. Think about who stops each goroutine before you write go.
time.Sleep to "wait for goroutines" only appears in toy examples; real code synchronises.
Example
package main
import (
"fmt"
"time"
)
func worker(id int, done chan<- string) {
time.Sleep(time.Duration(id) * 10 * time.Millisecond) // simulate work
done <- fmt.Sprintf("worker %d finished", id)
}
func main() {
done := make(chan string)
for id := 1; id <= 3; id++ {
go worker(id, done) // returns immediately
}
for range 3 {
fmt.Println(<-done) // wait for each result
}
}Remember
go f()starts f concurrently and returns immediately- Goroutines are cheap, but the program exits when main returns
- Every goroutine needs a defined way to finish
Watch out for
- Starting goroutines in main and returning before they finish, so their work silently never happens.