Golang / GoLang Concurrency Mastery Interview Questions
What is the 'done channel' pattern and why has context.Context largely superseded it?
Before context.Context was standardised in Go 1.7, a chan struct{} was the primary way to broadcast a stop signal. Closing the channel (rather than sending) is used because it unblocks all waiting receivers simultaneously — a broadcast, not a point-to-point signal.
// Done channel pattern (pre-1.7 idiom) done := make(chan struct{}) func startWorker(done <-chan struct{}, jobs <-chan Job) { for { select { case <-done: return // all goroutines unblock at once case job := <-jobs: process(job) } } } for i := 0; i < 5; i++ { go startWorker(done, jobs) } close(done) // broadcasts stop to all 5 workers in O(1) // Why close() instead of sending N values? // close() is O(1) and unblocks ALL receivers simultaneously. // Sending N values requires knowing N and sending N times. // Why context.Context is preferred today: // 1. Propagates deadlines/timeouts automatically // 2. Carries the reason: ctx.Err() returns Canceled or DeadlineExceeded // 3. Standard API â all stdlib network/IO functions accept context // 4. No manual channel plumbing through every function signature // Modern equivalent: ctx, cancel := context.WithCancel(context.Background()) for i := 0; i < 5; i++ { go func() { for { select { case <-ctx.Done(): return case job := <-jobs: process(job) } } }() } cancel() // equivalent to close(done)
More Related questions...