Skip to content
Development
Skill

/golang-concurrency

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

From plugin
cc-skills-golang
3.3k46 skills
Install
$ npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/golang-concurrency

Context preview

The summary Claude sees to decide when to auto-load this skill.

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

SKILL.md

golang-concurrency.SKILL.md
name: golang-concurrency
description: "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)."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
metadata:
  author: samber
  version: "1.2.1"
  openclaw:
    emoji: "⚡"
    homepage: https://github.com/samber/cc-skills-golang
    requires:
      bins:
        - go
    install: []
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent AskUserQuestion
paths:
  - "**/*.go"

**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:**

  • **Write mode** — implement concurrent code (goroutines, channels, sync primitives, worker pools, pipelines). Follow the sequential instructions below.
  • **Review mode** — reviewing a PR's concurrent code changes. Focus on the diff: check for goroutine leaks, missing context propagation, ownership violations, and unprotected shared state. Sequential.
  • **Audit mode** — auditing existing concurrent code across a codebase. Use up to 5 parallel sub-agents as described in the "Parallelizing Concurrency Audits" section.

> **Community default.** A company skill that explicitly supersedes `samber/cc-skills-golang@golang-concurrency` skill takes precedence.

Go Concurrency Best Practices

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.

Core Principles

1. **Every goroutine must have a clear exit** — without a shutdown mechanism (context, done channel, WaitGroup), they leak and accumulate until the process crashes 2. **Share memory by communicating** — channels transfer ownership explicitly; mutexes protect shared state but make ownership implicit 3. **Send copies, not pointers** on channels — sending pointers creates invisible shared memory, defeating the purpose of channels 4. **Only the sender closes a channel** — closing from the receiver side panics if the sender writes after close 5. **Specify channel direction** (`chan<-`, `<-chan`) — the compiler prevents misuse at build time 6. **Default to unbuffered channels** — larger buffers mask backpressure; use them only with measured justification 7. **Always include `ctx.Done()` in select** — without it, goroutines leak after caller cancellation 8. **Avoid repeated `time.After` in hot loops** — each call allocates a timer and creates unnecessary churn; use `time.NewTimer` + `Reset` for long-running loops 9. **Track goroutine leaks in tests** with `go.uber.org/goleak`

For detailed channel/select code examples, see [Channels and Select Patterns](references/channels-and-select.md).

Channel vs Mutex vs Atomic

| 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 |

WaitGroup vs errgroup

| 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 |

Sync Primitives Quick Reference

| 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 grou

Read more
Ships withcc-skills-golang

AI agent skills are reusable instruction sets that extend your coding assistant with domain-specific expertise, loaded on demand so they don't bloat your context. This repository covers Go-specific skills only (language, testing, security, observability, etc.)

Get the whole plugin

Other skills on cc-skills-golang.