Advanced Concurrency Patterns

Writing a goroutine is easy; coordinating thousands of them is the real challenge. Go provides several patterns and a specialized context package to manage the lifecycle, cancellation, and metadata of concurrent operations.


1. The Context Package: Lifecycle Management

The context package is the standard way to carry deadlines, cancellation signals, and other request-scoped values across API boundaries and between goroutines.

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // Always release context resources

select {
case <-doWork(ctx):
    fmt.Println("Work finished")
case <-ctx.Done():
    fmt.Println("Timed out:", ctx.Err())
}

2. WaitGroups: Waiting for Completion

A sync.WaitGroup is used to wait for a collection of goroutines to finish executing.

var wg sync.WaitGroup

for i := 0; i < 5; i++ {
    wg.Add(1)
    go func() {
        defer wg.Done()
        doWork()
    }()
}

wg.Wait() // Blocks until all 5 goroutines call Done()

3. The Fan-Out, Fan-In Pattern


4. Sync.Once and Atomic Operations


Interview Pro-Tips: What is a Goroutine Leak?

If an interviewer asks how to debug memory issues in Go:


Technical Summary

  1. Context: The standard for safe cancellation and timeouts.
  2. Synchronization: Use WaitGroups for completion and Mutexes for shared state.
  3. Safety: Avoid "Naked" goroutines; always have a plan for how they will terminate.