Lightweight concurrent functions started with the go keyword.
Concurrency Patterns
The go keyword and channels are primitives. Real programs combine them into a
handful of recurring shapes: worker pools, fan-out / fan-in, and
pipelines. Recognise these and most Go concurrency code becomes legible.
Worker pool
You have N units of work and want at most K of them running at once. Spawn K
goroutines that all read from the same jobs channel:
Key rules:
- Producers close
jobswhen no more work is coming. Workers exit naturally whenrangedrains. resultsis closed only after all senders finish — track them with aWaitGroup. Closing a channel that still has senders panics.- Output order is non-deterministic; if order matters, send
{idx, value}records and sort at the end.
Fan-out, fan-in
Fan-out: many workers read from one upstream channel (the pattern above). Fan-in: many upstream channels merge into one downstream channel.
func merge(cs ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
wg.Add(len(cs))
for _, c := range cs {
go func(c <-chan int) {
defer wg.Done()
for v := range c { out <- v }
}(c)
}
go func() { wg.Wait(); close(out) }()
return out
}
Same closing rule: out closes only after every input has drained.
Pipeline (stages connected by channels)
Each stage is a goroutine reading from one channel and writing to the next:
gen := func(nums ...int) <-chan int {
out := make(chan int)
go func() { defer close(out); for _, n := range nums { out <- n } }()
return out
}
sq := func(in <-chan int) <-chan int {
out := make(chan int)
go func() { defer close(out); for n := range in { out <- n * n } }()
return out
}
for v := range sq(sq(gen(2, 3))) {
fmt.Println(v) // 16, 81
}
Each stage owns its output channel and closes it on the way out. Composes
cleanly — adding a filter stage is one more function.
When to skip channels entirely
Channels aren't a hammer. If you're guarding shared state, sync.Mutex is
simpler and faster. If you're batching independent calls and want the first
error to cancel the rest, errgroup gives you the pattern
in three lines.