skills/golang-concurrency/SKILL.md
Golang concurrency design — goroutine lifecycle and leak prevention, channels and `select`, channel ownership and direction, `sync.Mutex`/`RWMutex`/`sync.Map`/`sync.Once`/atomics, `errgroup`, `singleflight`, worker pools, and fan-out/fan-in pipelines. Use when writing or reviewing concurrent Go code, when choosing between channels and mutexes, when protecting a shared map or counter, or when a goroutine has no clear exit. Not for defensive coding unrelated to concurrency such as nil panics, slice aliasing, or numeric overflow (→ See `samber/cc-skills-golang@golang-safety` skill), and not for debugging a specific hung, crashing, or racing program after the fact (→ See `samber/cc-skills-golang@golang-troubleshooting` skill).
npx skillsauth add samber/cc-skills-golang golang-concurrencyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
| Scenario | Use | Why |
| --- | --- | --- |
| Passing data between goroutines | Channel | Communicates ownership transfer |
| Coordinating goroutine lifecycle | Channel + context | Clean shutdown with select |
| Protecting shared struct fields | sync.Mutex / sync.RWMutex | Simple critical sections |
| Simple counters, flags | sync/atomic | Lock-free, lower overhead |
| Many readers, few writers on a map | sync.Map | Optimized for read-heavy workloads. Concurrent map read/write causes a hard crash |
| Caching expensive computations | sync.Once / singleflight | Execute once or deduplicate |
| Need | Use | Why |
| --- | --- | --- |
| Wait for goroutines, errors not needed | sync.WaitGroup | Fire-and-forget |
| Wait + collect first error | errgroup.Group | Error propagation |
| Wait + cancel siblings on first error | errgroup.WithContext | Context cancellation on error |
| Wait + limit concurrency | errgroup.SetLimit(n) | Built-in worker pool |
| Primitive | Use case | Key notes |
| --- | --- | --- |
| sync.Mutex | Protect shared state | Keep critical sections short; never hold across I/O |
| sync.RWMutex | Many readers, few writers | Never upgrade RLock to Lock (deadlock) |
| sync/atomic | Simple counters, flags | Prefer typed atomics (Go 1.19+): atomic.Int64, atomic.Bool |
| sync.Map | Concurrent map, read-heavy | No explicit locking; use RWMutex+map when writes dominate |
| sync.Pool | Reuse temporary objects | Always Reset() before Put(); reduces GC pressure |
| sync.Once | One-time initialization | Go 1.21+: OnceFunc, OnceValue, OnceValues |
| sync.WaitGroup | Waiting for simple goroutines | Go 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/singleflight | Deduplicate concurrent calls | Cache stampede prevention |
| x/sync/errgroup | Goroutine group + errors | SetLimit(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 documentation| Mistake | Fix |
| --- | --- |
| Fire-and-forget goroutine | Provide stop mechanism (context, done channel) |
| Closing channel from receiver | Only the sender closes |
| time.After in hot loop | Reuse time.NewTimer + Reset |
| Missing ctx.Done() in select | Always select on context to allow cancellation |
| Unbounded goroutine spawning | Use errgroup.SetLimit(n) or semaphore |
| Sharing pointer via channel | Send copies or immutable values |
| wg.Add inside goroutine | Call Add before go — Wait may return early otherwise |
| Forgetting -race in CI | Always run go test -race ./... |
| Mutex held across I/O | Keep 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 guidelinesThe goroutine leak profile (experimental behind GOEXPERIMENT=goroutineleakprofile in Go 1.26) is generally available in runtime/pprof since Go 1.27 — no build flag required. It is a useful production-oriented leak signal alongside the existing tools below.
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 ./...development
Golang refactoring — safe, at-scale restructuring of existing Go code: a coverage-adaptive safety net, behavior-preserving transforms (gopls Rename/Extract, `gofmt -r`, `gopatch`), the Fowler catalog mapped to Go, breaking import cycles, and small stacked PRs. Apply when a function or type has grown too large, a code smell blocks a feature, or the user asks to refactor Go code — also for renaming at scale, extracting functions or interfaces, moving code between packages, or planning a multi-step refactor. Target styles owned elsewhere → See `samber/cc-skills-golang@golang-naming` (renames), `samber/cc-skills-golang@golang-project-layout` (splits), `samber/cc-skills-golang@golang-modernize` (idioms), `samber/cc-skills-golang@golang-code-style` (control flow), `samber/cc-skills-golang@golang-design-patterns` (patterns/DI).
tools
Golang semantic code intelligence via `gopls`, the official Go language server — go-to-definition, find references, call/implementation hierarchy, workspace symbol search, package API discovery, diagnostics, safe rename, refactors (extract/inline/fill/rewrite code actions), formatting, and generated tests. Reaches an agent via gopls's own MCP server (`go_*` tools), Claude Code's native `LSP` tool, or the `gopls` CLI. Use when navigating or refactoring Go code — jumping to a definition, finding call sites before a rename, understanding a file's or package's dependencies, running diagnostics after an edit, or extracting/inlining/renaming. Not for the published ecosystem — packages not in your `go.mod`, versions, licenses, importers — → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`). Not for a whole-tree vulnerability audit → See `samber/cc-skills-golang@golang-security` skill (`govulncheck`).
tools
Golang package and module lookup via `godig`, a pkg.go.dev API client (CLI + MCP server). Use for any Go/Golang library's documentation, API signatures, symbols, usage examples, which versions exist, licenses, whether a dependency has CVEs, or who imports a package — prefer this over Context7 for any Go package or module. Read-only, no auth. Not for upgrading dependencies (→ See `samber/cc-skills-golang@golang-dependency-management` skill), choosing a library (→ See `samber/cc-skills-golang@golang-popular-libraries` skill), or local symbols and an already-used dependency's resolved source, call sites, and generic instantiations (→ See `samber/cc-skills-golang@golang-gopls` skill).
development
Golang skills orchestrator — always active on any Golang coding, review, debug, or setup task. Reads the task context and loads the most relevant skills from samber/cc-skills-golang, often multiple at once: writing a gRPC service loads golang-grpc + golang-testing + golang-error-handling; debugging a panic loads golang-troubleshooting + golang-safety; auditing security loads golang-security + golang-lint + golang-safety. Also: disambiguates competing clusters when two skills seem to overlap (performance vs benchmark vs troubleshooting, samber/lo vs mo vs ro, DI cluster, safety vs security), and configures the project's agent-config file (CLAUDE.md, AGENTS.md, GEMINI.md, Cursor rules, or Copilot instructions) to force-trigger skills in a project (/golang-how-to configure).