# Golang Concurrency > Patrones de concurrencia en Go: úsalo al escribir o revisar código concurrente con goroutines, channels, select, locks, sync primitives, errgroup, singleflight, worker pools o pipelines fan-out/fan-in. Fuente: https://skillsagentes.com/skills/samber/cc-skills-golang/golang-concurrency Markdown: https://skillsagentes.com/skills/samber/cc-skills-golang/golang-concurrency.md Repositorio: https://github.com/samber/cc-skills-golang Autor: samber Licencia: MIT Actualizado: el mes pasado Coste de contexto: 87 tok instalada, 2.3k tok al activarse, 10.8k tok con todos los archivos del bundle Bundle: 5 archivos, 42 KB Permisos que pide: read edit write glob grep bash(go:*) bash(golangci-lint:*) bash(git:*) agent askuserquestion ## Instalación Un skill son archivos markdown: los mismos archivos valen para cualquier agente y lo único que cambia es el directorio de destino, es decir la bandera `--agent`. Añade `-g` para instalarlo en todos los proyectos de la máquina. ```bash # Claude Code npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent claude-code # Cursor npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent cursor # Codex npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent codex # Gemini CLI npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent gemini # Windsurf npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent windsurf # Cline npx -y skills add samber/cc-skills-golang --skill golang-concurrency --agent cline ``` ## Qué hace - Aplica principios de concurrencia estructurada en Go: ownership claro, salida predecible y propagación de errores para cada goroutine - Guía la elección entre channels, mutex, atomics, sync.Map y errgroup según el escenario - Revisa diffs en busca de goroutine leaks, falta de context.Done(), y violaciones de ownership de channels - Orquesta hasta 5 sub-agentes paralelos para auditar concurrencia en bases de código grandes - Detecta antipatrones comunes: time.After en loops calientes, cierre de channel desde el receptor, spawning ilimitado ## Cuándo usarla - Escribes o revisas código Go con goroutines, channels, select, locks o sync primitives - Necesitas elegir entre channels y mutexes, o entre WaitGroup y errgroup - Detectas goroutine leaks, race conditions o problemas de ownership de channels - Auditas patrones de fan-out/fan-in, worker pools o singleflight en un codebase grande ## Qué la activa - "Revisa este PR que añade goroutines y channels a este módulo" - "Ayúdame a implementar un worker pool con errgroup en Go" - "Audita el codebase para detectar goroutine leaks y race conditions" - "¿Debo usar un channel o un mutex para proteger este struct?" ## Antes de instalar - Requiere el binario go instalado y, para checks de raza, ejecutar go test -race ./.... - Necesita en el PATH: curl ## Archivos - SKILL.md — 9 KB - evals/evals.json — 15 KB - references/channels-and-select.md — 4 KB - references/pipelines.md — 7 KB - references/sync-primitives.md — 8 KB ## SKILL.md Reproducido tal cual desde samber/cc-skills-golang bajo MIT. Esta sección es el documento original y está en inglés. **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:** Use `ultracode` for auditing concurrent code across a large codebase — orchestrate the five sub-agents described in the "Parallelizing Concurrency Audits" section and consolidate their findings into one report. **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 group + errors | `SetLimit(n)` replaces hand-rolled worker pools | For detailed examples and anti-patterns, see [Sync Primitives Deep Dive](references/sync-primitives.md). ## Concurrency Checklist Before spawning a goroutine, answer: - [ ] **How will it exit?** — context cancellation, channel close, or explicit signal - [ ] **Can I signal it to stop?** — pass `context.Context` or done channel - [ ] **Can I wait for it?** — `sync.WaitGroup` or `errgroup` - [ ] **Who owns the channels?** — creator/sender owns and closes - [ ] **Should this be synchronous instead?** — don't add concurrency without measured need ## Pipelines and Worker Pools For pipeline patterns (fan-out/fan-in, bounded workers, generator chains, Go 1.23+ iterators, `samber/ro`), see [Pipelines and Worker Pools](references/pipelines.md). ## Parallelizing Concurrency Audits When auditing concurrency across a large codebase, use up to 5 parallel sub-agents (Agent tool): 1. Find all goroutine spawns (`go func`, `go method`) and verify shutdown mechanisms 2. Search for mutable globals and shared state without synchronization 3. Audit channel usage — ownership, direction, closure, buffer sizes 4. Find `time.After` in loops, missing `ctx.Done()` in select, unbounded spawning 5. Check mutex usage, `sync.Map`, atomics, and thread-safety documentation ## Common Mistakes | 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 | ## Cross-References - -> See `samber/cc-skills-golang@golang-performance` skill for false sharing, cache-line padding, `sync.Pool` hot-path patterns - -> See `samber/cc-skills-golang@golang-context` skill for cancellation propagation and timeout patterns - -> See `samber/cc-skills-golang@golang-safety` skill for concurrent map access and race condition prevention - -> See `samber/cc-skills-golang@golang-troubleshooting` skill for debugging goroutine leaks and deadlocks - -> See `samber/cc-skills-golang@golang-design-patterns` skill for graceful shutdown patterns - -> See `samber/cc-skills-golang@golang-continuous-integration` skill for automated AI-driven code review in CI using these guidelines ### Go 1.26 experimental goroutine leak profile For 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: - tests: `go.uber.org/goleak` - runtime count: `runtime.NumGoroutine()` - stack dump: `/debug/pprof/goroutine?debug=2` - race checks: `go test -race ./...` ## References - [Go Concurrency Patterns: Pipelines](https://go.dev/blog/pipelines) - [Effective Go: Concurrency](https://go.dev/doc/effective_go#concurrency) ## Dónde encaja - Categoría: [Herramientas para desarrolladores](https://skillsagentes.com/categorias/herramientas-desarrollo.md) — Skills que cambian cómo tu agente escribe, revisa y despliega código. - Creador: [samber](https://skillsagentes.com/creators/samber.md) — 0 skills en el directorio - [Todas las skills](https://skillsagentes.com/skills.md) - [Ranking de instalaciones](https://skillsagentes.com/ranking.md) ## Otras skills del mismo repositorio - [Golang Lint](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-lint.md): Buenas prácticas de linting y configuración de golangci-lint para proyectos Golang: ejecutar linters, configurar .golangci.yml, suprimir avisos con nolint, interpretar salidas y elegir linters. - [Golang How To](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-how-to.md): Orquestador de skills de Golang, siempre activo en cualquier tarea de código, revisión, debug o setup: carga las skills más relevantes de samber/cc-skills-golang, a menudo varias a la vez. - [Golang Benchmark](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-benchmark.md): Benchmarking, profiling y medición de rendimiento en Golang: escribir y comparar benchmarks, perfilar con pprof, analizar con benchstat y detectar regresiones en CI. - [Golang Testing](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-testing.md): Tests de Golang listos para producción: table-driven, suites y mocks con testify, tests paralelos, fuzzing, fixtures, detección de fugas de goroutines con goleak, snapshot testing, cobertura, tests de integración. - [Golang Performance](https://skillsagentes.com/skills/samber/cc-skills-golang/golang-performance.md): Patrones y metodología de optimización de rendimiento en Golang: si hay cuello de botella X, aplica el patrón Y, una vez que profiling o benchmarks ya lo identificaron. --- Skills Agentes · [Índice de páginas en markdown](https://skillsagentes.com/sitemap.md) · [Inicio](https://skillsagentes.com/index.md)