Go Concurrency Patterns

Goroutines, channels, select, sync primitives, and common concurrency patterns in Go.

The data

Concepts

NameKeywordDescriptionExampleNotesPattern
GoroutinesgoLightweight threads managed by Go runtime; cheap to create (few KB stack).go func() { fmt.Println("running in goroutine") }() thousands of concurrent goroutines possible; multiplexed onto OS threadsnull
ChannelschanTyped conduits for communication between goroutines; synchronous or buffered.ch := make(chan int); go func() { ch <- 42 }(); val := <-chBlocking by default; unbuffered channels synchronize goroutinesnull
Buffered Channelsmake(chan T, n)Channels with capacity; sender blocks only when buffer full.bufCh := make(chan string, 5); bufCh <- "msg"; // non-blocking if spaceUseful for queue-like patterns; decouples sender/receiver ratesnull
Select StatementselectWait on multiple channel operations; like switch for channels.select { case msg := <-ch1: fmt.Println(msg) case msg := <-ch2: fmt.Println(msg) case <-time.After(time.Second): fmt.Println("timeout") }Random choice if multiple ready; default case non-blockingnull
WaitGroupsync.WaitGroupWait for a collection of goroutines to finish; Add, Done, Wait.var wg sync.WaitGroup; wg.Add(2); go func(){ defer wg.Done(); ... }(); wg.Wait()Must call Done exactly once per Add; typically defer wg.Done()null
Mutex (Mutual Exclusion)sync.MutexProtect shared memory; Lock/Unlock ensure exclusive access.var mu sync.Mutex; mu.Lock(); counter++; mu.Unlock()Prefer channels over mutexes when possible (communicating vs sharing)null
Worker Pool PatternnullDistribute work across multiple workers; collect results.jobs := make(chan Job); results := make(chan Result); for w:=1; w<=3; w++ { go worker(jobs, results) }; for j:=range jobs { jobs <- j }; close(results); for r:=range results { ... }Classic pipeline: distribute tasks, process concurrently, collectFan-out / Fan-in
Context Packagecontext.ContextCarry deadlines, cancellation signals, and request-scoped values across API boundaries.ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second); defer cancel(); select { case <-ctx.Done(): fmt.Println("timeout") }Use for cancellation, timeouts, and passing request-scoped datanull

Fetch the same bytes

The static files are identical to what the API returns, but with no rate limit and no server round trip. Use the API when you want a query and a content type; use the files when you want to cache one document.

curl "https://yjtoon.com/api/dataset/go-concurrency-patterns?format=toon"
const res = await fetch(
  "https://yjtoon.com/static-data/dataset/go-concurrency-patterns.toon"
);
const toon = await res.text();

Rate limit: 120 requests per minute per IP, no key and no signup. API reference →

Topics

  • go
  • golang
  • concurrency
  • goroutines
  • channels