Notes — Module 12: Advanced Concurrency Patterns¶
These are your personal study notes. Write freely and honestly. Incomplete notes are fine — they show where your understanding still needs work. Return to this file to add insights as they develop over time.
Module: [[go/12. Advanced Concurrency Patterns]] Topic: [[go]] Date started: YYYY-MM-DD Status: In progress
Concept Map¶
Sketch how the concepts in this module relate to each other. Fill in the Mermaid diagram.
mindmap
root((Advanced Concurrency))
context.Context
WithCancel / WithTimeout / WithDeadline
WithValue pitfalls
first-parameter convention
ctx.Done() and ctx.Err()
propagation through call tree
Pipelines
stages linked by channels
defer close(out)
cancellation via ctx.Done() on sends
Fan-Out / Fan-In
one input to many workers
merge channels with WaitGroup
Worker Pools
fixed N workers
jobs channel with back-pressure
semaphore via buffered channel
Rate Limiting
time.Ticker simple case
golang.org/x/time/rate token bucket
Atomics
atomic.Int64 / atomic.Pointer
CAS for conditional updates
non-composable
sync.Pool
object reuse / allocation reduction
GC may clear at any time
errgroup
WithContext pattern
first error cancels group
g.Wait() return
Goroutine Leaks
always provide exit path
buffer-of-1 trick
goleak in tests
Graceful Shutdown
signal.NotifyContext
drain phase with timeout
wg.Wait + select
Alternative: draw this on paper, photo it, and link the image here.
Key Insights¶
The "aha moments" — the things that, once understood, made the rest clear. Be specific: "I finally understood X because Y" is more useful than "X makes sense".
- Context is not optional plumbing: I finally understood that
context.Contextis not boilerplate — it's the mechanism by which every function in a call tree can be told "stop, the client gave up". Without it, goroutines and database queries continue running after the HTTP response has already been sent. - Every goroutine needs a termination condition: The goroutine leak mental model clicked when I realized: a goroutine is like a thread you start but forget to join. Unless it has a
ctx.Done(), a closed channel, or a done condition, it runs until the process exits — silently consuming memory. - Add insights as you discover them
My Understanding¶
Explain the core concepts in your own words, as if teaching them to someone else. If you can't explain it simply, you don't understand it well enough yet.
context.Context¶
Your explanation here
What I'm still unsure about: (e.g., when exactly the deadline timer goroutine is cleaned up)
Pipelines and cancellation¶
Your explanation here
What I'm still unsure about: (e.g., what happens if a stage panics — does the pipeline drain cleanly?)
Worker pool vs semaphore¶
Your explanation here
What I'm still unsure about: (e.g., when to prefer a semaphore over a pool)
errgroup¶
Your explanation here
What I'm still unsure about: (e.g., whether errgroup.SetLimit sets a semaphore on goroutine count)
Connections to Other Topics¶
How does this module connect to things you already know?
| This module's concept | Connects to | How |
|---|---|---|
| context.Context cancellation | [[go/9. Concurrency]] — channels and select | ctx.Done() is just a receive-only channel; the select pattern is from Module 9 |
| errgroup error propagation | [[go/8. Error Handling]] | errgroup returns the first non-nil error using the same error interface and wrapping conventions |
| atomic.Int64 memory guarantees | [[go/17. Runtime Internals and the Memory Model]] | atomics provide sequential consistency — the happens-before guarantees are formally defined in the memory model |
| Goroutine leaks | [[concurrency]] | Shared concept across languages: a goroutine is like a thread that must be explicitly given a way to terminate |
Questions That Arose¶
Log questions as they appear. Don't stop to answer them now — just capture them. Then move the serious ones to QUESTIONS.md.
- Does
errgrouplimit the number of concurrent goroutines (like a pool), or does it just aggregate errors? → added to QUESTIONS.md as Q001 - Is
sync.Poolsafe to use for objects that containsync.Mutex? → needs investigation - What happens if
context.WithValueis called with the same key twice? Does the second value shadow the first? → might be in pkg.go.dev/context docs
Code Snippets Worth Remembering¶
Patterns, idioms, or examples that captured something important.
The canonical context-aware operation¶
Why I'm saving this: Every context-aware operation is a select that races work against ctx.Done(). This is the atomic unit of context integration.
defer cancel() — always, immediately¶
ctx, cancel := context.WithTimeout(parent, 5*time.Second)
defer cancel() // line 2, right after line 1. Never skip this.
Why I'm saving this: The resource leak from missing cancel() is invisible until the service is under load. Defer it immediately — it's always safe to call and always required.
Worker pool skeleton¶
jobs := make(chan T, N)
results := make(chan R)
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go worker(&wg, jobs, results)
}
go func() { wg.Wait(); close(results) }()
Why I'm saving this: This is the repeatable structure for every bounded worker pool. Fill jobs, close it, range over results.
What Tripped Me Up¶
Mistakes I made, misconceptions I had, things that confused me more than they should have. Being honest here helps you later.
- Missing
defer cancel()— I initially skipped it when the timeout fires beforecancel()anyway, but learned that the timer goroutine leaks without it even after the context expires. - Closing a channel from the receiver — I tried to close the
outchannel from the fan-in consumer goroutine, which panics if any sender fires a send after the close.
Summary in My Own Words¶
Write a 3–5 sentence summary of this entire module without looking at any notes. If you can't do this, you need more study time.
Write your summary here after completing the module.
Last updated: YYYY-MM-DD