Persona: You are a Go concurrency engineer. You assume every goroutine is a liability until proven necessary — correctness and leak-freedom come before performance.
Orchestration mode: Fan out the five sub-agents described in the "Parallelizing Concurrency Audits" section for auditing concurrent code across a large codebase, and consolidate their findings into one report. On Claude Code, use ultracode to opt into multi-agent orchestration explicitly.
Modes:
Community default. A company skill that explicitly supersedes
samber/cc-skills-golang@golang-concurrencyskill takes precedence.
Go's concurrency model is built on goroutines and channels. Goroutines are cheap but not free — every goroutine you spawn is a resource you must manage. The goal is structured concurrency: every goroutine has a clear owner, a predictable exit, and proper error propagation.
chan<-, <-chan) — the compiler prevents misuse at build timectx.Done() in select — without it, goroutines leak after caller cancellationtime.After in hot loops — each call allocates a timer and creates unnecessary churn; use time.NewTimer + Reset for long-running loopsgo.uber.org/goleakFor detailed channel/select code examples, see Channels and Select Patterns.
ScenarioUseWhyPassing data between goroutinesChannelCommunicates ownership transferCoordinating goroutine lifecycleChannel + contextClean shutdown with selectProtecting shared struct fieldssync.Mutex / sync.RWMutexSimple critical sectionsSimple counters, flagssync/atomicLock-free, lower overheadMany readers, few writers on a mapsync.MapOptimized for read-heavy workloads. Concurrent map read/write causes a hard crashCaching expensive computationssync.Once / singleflightExecute once or deduplicate
NeedUseWhyWait for goroutines, errors not neededsync.WaitGroupFire-and-forgetWait + collect first errorerrgroup.GroupError propagationWait + cancel siblings on first errorerrgroup.WithContextContext cancellation on errorWait + limit concurrencyerrgroup.SetLimit(n)Built-in worker pool
PrimitiveUse caseKey notessync.MutexProtect shared stateKeep critical sections short; never hold across I/Osync.RWMutexMany readers, few writersNever upgrade RLock to Lock (deadlock)sync/atomicSimple counters, flagsPrefer typed atomics (Go 1.19+): atomic.Int64, atomic.Bool``sync.MapConcurrent map, read-heavyNo explicit locking; use RWMutex +map when writes dominatesync.PoolReuse temporary objectsAlways Reset() before Put(); reduces GC pressuresync.OnceOne-time initializationGo 1.21+: OnceFunc, OnceValue, OnceValues``sync.WaitGroupWaiting for simple goroutinesGo 1.25+: prefer wg.Go(func(){ ... }) for fire-and-wait tasks that do not panic and do not need error propagation. For Go <1.25 use Add/ Done. For errors/cancellation/limits, use errgroup with context.x/sync/singleflightDeduplicate concurrent callsCache stampede preventionx/sync/errgroupGoroutine group + errorsSetLimit(n) replaces hand-rolled worker pools
For detailed examples and anti-patterns, see Sync Primitives Deep Dive.
Before spawning a goroutine, answer:
context.Context or done channelsync.WaitGroup or errgroupFor pipeline patterns (fan-out/fan-in, bounded workers, generator chains, Go 1.23+ iterators, samber/ro), see Pipelines and Worker Pools.
When auditing concurrency across a large codebase, use up to 5 parallel sub-agents:
go func, go method) and verify shutdown mechanismstime.After in loops, missing ctx.Done() in select, unbounded spawningsync.Map, atomics, and thread-safety documentationMistakeFixFire-and-forget goroutineProvide stop mechanism (context, done channel)Closing channel from receiverOnly the sender closestime.After in hot loopReuse time.NewTimer + ResetMissing ctx.Done() in selectAlways select on context to allow cancellationUnbounded goroutine spawningUse errgroup.SetLimit(n) or semaphoreSharing pointer via channelSend copies or immutable valueswg.Add inside goroutineCall Add before go — Wait may return early otherwiseForgetting -race in CIAlways run go test -race ./...Mutex held across I/OKeep critical sections short
samber/cc-skills-golang@golang-performance skill for false sharing, cache-line padding, sync.Pool hot-path patternssamber/cc-skills-golang@golang-context skill for cancellation propagation and timeout patternssamber/cc-skills-golang@golang-safety skill for concurrent map access and race condition preventionsamber/cc-skills-golang@golang-troubleshooting skill for debugging goroutine leaks and deadlockssamber/cc-skills-golang@golang-design-patterns skill for graceful shutdown patternssamber/cc-skills-golang@golang-continuous-integration skill for automated AI-driven code review in CI using these guidelinesFor Go 1.26 diagnostics, there is an experimental goroutine leak profile. It is useful for production-oriented leak investigation, but is gated by GOEXPERIMENT=goroutineleakprofile; do not rely on it as default stable behavior.
Typical usage when the experiment is enabled:
bash
curl http://localhost:6060/debug/pprof/goroutineleak?debug=2
go tool pprof http://localhost:6060/debug/pprof/goroutineleak
Keep existing tools:
go.uber.org/goleakruntime.NumGoroutine()/debug/pprof/goroutine?debug=2go test -race ./...