← ClaudeAtlas

go-concurrencylisted

Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker pools, or fan-out/fan-in pipelines. Apply proactively whenever a goroutine is spawned, a shared field is mutated, or a channel is created, even if the user has not asked about concurrency. Does not cover context.Context patterns (see go-context).
muratmirgun/gophers · ★ 6 · Data & Documents · score 84
Install: claude install-skill muratmirgun/gophers
# Go Concurrency Goroutines are cheap, but every one you spawn is a resource you must own. The goal is **structured concurrency**: each goroutine has a clear owner, a predictable exit, and a way for the caller to wait and collect errors. ## Core Rules 1. **Never start a goroutine without knowing how it will stop.** A blocked goroutine is not garbage-collected — it leaks. 2. **The caller must be able to wait.** Use `sync.WaitGroup`, `errgroup.Group`, or an explicit done channel. 3. **No goroutines in `init()`.** Expose `Start`/`Stop`/`Shutdown` so callers control the lifecycle. 4. **Share by communicating.** Default to channels; reach for `sync.Mutex` only when the problem is genuinely "protect a shared field". 5. **Only the sender closes a channel.** Closing from the receiver side panics on the next send. 6. **Specify channel direction** (`chan<-`, `<-chan`) at function boundaries — the compiler catches misuse. 7. **Always include `ctx.Done()` in `select`.** Without it, the goroutine cannot be cancelled. 8. **Test for leaks** with [`go.uber.org/goleak`](https://pkg.go.dev/go.uber.org/goleak). ## Primitive Decision | Need | Use | Why | |---|---|---| | Pass a value from producer to consumer | Channel | Transfers ownership explicitly | | Wait for N fire-and-forget goroutines | `sync.WaitGroup` (Go 1.25: `wg.Go`) | No error needed | | Wait + collect first error + cancel siblings | `errgroup.WithContext` | Structured failure | | Bound concurrency (worker pool) | `errgroup.Set