go-concurrency
Use when writing concurrent Go code — goroutines, channels, mutexes, or thread-safety guarantees. Also use when parallelizing work, fixing data races, or protecting shared state, even if the user doesn't explicitly mention concurrency primitives. Does not cover context.Context patterns (see go-context).
What this skill does
# Go Concurrency
## Goroutine Lifetimes
> **Normative**: When you spawn goroutines, make it clear when or whether they
> exit.
Goroutines can leak by blocking on channel sends/receives. The GC **will not
terminate** a blocked goroutine even if no other goroutine holds a reference to
the channel. Even non-leaking in-flight goroutines cause panics (send on closed
channel), data races, memory issues, and resource leaks.
### Core Rules
1. **Every goroutine needs a stop mechanism** — a predictable end time, a
cancellation signal, or both
2. **Code must be able to wait** for the goroutine to finish
3. **No goroutines in `init()`** — expose lifecycle methods (`Close`, `Stop`,
`Shutdown`) instead
4. **Keep synchronization scoped** — constrain to function scope, factor logic
into synchronous functions
```go
// Good: Clear lifetime with WaitGroup
var wg sync.WaitGroup
for item := range queue {
wg.Add(1)
go func() { defer wg.Done(); process(ctx, item) }()
}
wg.Wait()
```
```go
// Bad: No way to stop or wait
go func() { for { flush(); time.Sleep(delay) } }()
```
**Test for leaks** with [go.uber.org/goleak](https://pkg.go.dev/go.uber.org/goleak).
> **Principle**: Never start a goroutine without knowing how it will stop.
> Read [references/GOROUTINE-PATTERNS.md](references/GOROUTINE-PATTERNS.md) when
> implementing stop/done channel patterns, goroutine waiting strategies, or
> lifecycle-managed workers.
---
## Share by Communicating
> "Do not communicate by sharing memory; instead, share memory by communicating."
This is Go's foundational concurrency design principle. Use **channels** for
ownership transfer and orchestration — when one goroutine produces a value and
another consumes it. Use **mutexes** when multiple goroutines access shared
state and channels would add unnecessary complexity.
**Default to channels.** Fall back to `sync.Mutex` / `sync.RWMutex` when the
problem is naturally about protecting a shared data structure (e.g., a cache or
counter) rather than passing data between goroutines.
---
## Synchronous Functions
> **Normative**: Prefer synchronous functions over asynchronous ones.
| Benefit | Why |
|---|---|
| Localized goroutines | Lifetimes easier to reason about |
| Avoids leaks and races | Easier to prevent resource leaks and data races |
| Easier to test | Check input/output without polling |
| Caller flexibility | Caller adds concurrency when needed |
> **Advisory**: It is quite difficult (sometimes impossible) to remove
> unnecessary concurrency at the caller side. Let the caller add concurrency
> when needed.
> Read [references/GOROUTINE-PATTERNS.md](references/GOROUTINE-PATTERNS.md) when
> writing synchronous-first APIs that callers may wrap in goroutines.
---
## Zero-value Mutexes
The zero-value of `sync.Mutex` and `sync.RWMutex` is valid — almost never need
a pointer to a mutex.
```go
// Good: Zero-value is valid // Bad: Unnecessary pointer
var mu sync.Mutex mu := new(sync.Mutex)
```
**Don't embed mutexes** — use a named `mu` field to keep `Lock`/`Unlock` as
implementation details, not exported API.
> Read [references/SYNC-PRIMITIVES.md](references/SYNC-PRIMITIVES.md) when
> implementing mutex-protected structs or deciding how to structure mutex fields.
---
## Channel Direction
> **Normative**: Specify channel direction where possible.
Direction prevents errors (compiler catches closing a receive-only channel),
conveys ownership, and is self-documenting.
```go
func produce(out chan<- int) { /* send-only */ }
func consume(in <-chan int) { /* receive-only */ }
func transform(in <-chan int, out chan<- int) { /* both */ }
```
### Channel Size: One or None
Channels should have size **zero** (unbuffered) or **one**. Any other size
requires justification for:
- How the size was determined
- What prevents the channel from filling under load
- What happens when writers block
```go
c := make(chan int) // unbuffered — Good
c := make(chan int, 1) // size one — Good
c := make(chan int, 64) // arbitrary — needs justification
```
> Read [references/SYNC-PRIMITIVES.md](references/SYNC-PRIMITIVES.md) when
> reviewing detailed channel direction examples with error-prone patterns.
---
## Atomic Operations
Use `atomic.Bool`, `atomic.Int64`, etc. (stdlib `sync/atomic` since Go 1.19, or
[go.uber.org/atomic](https://pkg.go.dev/go.uber.org/atomic)) for type-safe
atomic operations. Raw `int32`/`int64` fields make it easy to forget atomic
access on some code paths.
```go
// Good: Type-safe // Bad: Easy to forget
var running atomic.Bool var running int32 // atomic
running.Store(true) atomic.StoreInt32(&running, 1)
running.Load() running == 1 // race!
```
> Read [references/SYNC-PRIMITIVES.md](references/SYNC-PRIMITIVES.md) when
> choosing between sync/atomic and go.uber.org/atomic, or implementing atomic
> state flags in structs.
---
## Documenting Concurrency
> **Advisory**: Document thread-safety when it's not obvious from the operation
> type.
Go users assume read-only operations are safe for concurrent use, and mutating
operations are not. Document concurrency when:
1. **Read vs mutating is unclear** — e.g., a `Lookup` that mutates LRU state
2. **API provides synchronization** — e.g., thread-safe clients
3. **Interface has concurrency requirements** — document in type definition
---
## Context Usage
> For context.Context guidance (parameter placement, struct storage, custom
> types, derivation patterns), see the dedicated
> [go-context](../go-context/SKILL.md) skill.
---
## Buffer Pooling with Channels
Use a buffered channel as a free list to reuse allocated buffers. This "leaky
buffer" pattern uses `select` with `default` for non-blocking operations.
> Read [references/BUFFER-POOLING.md](references/BUFFER-POOLING.md) when
> implementing a worker pool with reusable buffers or choosing between
> channel-based pools and `sync.Pool`.
---
## Advanced Patterns
> Read [references/ADVANCED-PATTERNS.md](references/ADVANCED-PATTERNS.md) when
> implementing request-response multiplexing with channels of channels, or
> CPU-bound parallel computation across cores.
---
## Related Skills
- **Context propagation**: See [go-context](../go-context/SKILL.md) when passing cancellation, deadlines, or request-scoped values through goroutines
- **Error handling**: See [go-error-handling](../go-error-handling/SKILL.md) when propagating errors from goroutines or using errgroup
- **Defensive hardening**: See [go-defensive](../go-defensive/SKILL.md) when protecting shared state at API boundaries or using defer for cleanup
- **Interface design**: See [go-interfaces](../go-interfaces/SKILL.md) when choosing receiver types for types with sync primitives
### External Resources
- [Never start a goroutine without knowing how it will
stop](https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop)
— Dave Cheney
- [Rethinking Classical Concurrency
Patterns](https://www.youtube.com/watch?v=5zXAHh5tJqQ) — Bryan Mills
(GopherCon 2018)
- [When Go programs end](https://changelog.com/gotime/165) — Go Time podcast
- [go.uber.org/goleak](https://pkg.go.dev/go.uber.org/goleak) — Goroutine leak
detector for testing
- [go.uber.org/atomic](https://pkg.go.dev/go.uber.org/atomic) — Type-safe
atomic operations
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.