К основному содержанию
скилл CX Codex

go-concurrency-review — скилл для Claude Code: проверка Go-кода

Скилл проверяет конкурентный код на Go: жизненный цикл горутин, каналы, общие данные и передачу контекста. Пригодится для ревью, поиска гонок и проектирования конвейеров.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add eduardo-sl/go-agent-skills --skill go-concurrency-review -a claude-code
Открыть на GitHub

Что делает go-concurrency-review

Скилл работает в режимах реализации, ревью изменений и поиска утечек или гонок. При полном аудите он предлагает отдельно проверить завершение каждой горутины, защиту общего состояния, закрытие каналов и передачу context.Context. Результаты нужно привязывать к файлу и строке, а завершать аудит запуском go test -race ./....

В рекомендациях разобрано, когда выбирать каналы, sync.Mutex, атомики, sync.OnceValue и errgroup. Подробности по каналам, примитивам синхронизации и шаблонам горутин вынесены в справочные файлы, которые агент читает по необходимости. Для работы нужен Go toolchain; обнаружение гонок требует cgo и CGO_ENABLED=1.

Горутинам нужен понятный путь завершения, а отправки в канал должны учитывать отмену контекста. Это стоит проверить до внедрения: без cgo проверка через race detector не сработает. Скилл не предназначен для общего стилевого ревью или проектирования HTTP-обработчиков.

Какие задачи решает

  • найти горутины без пути завершения
  • проверить защиту данных, доступных из нескольких горутин
  • выявить риск отправки в закрытый канал
  • проверить передачу отмены контекста в блокирующие вызовы
  • спланировать аудит конкурентности по независимым проходам

Примеры запросов агенту

  • Проверь изменения на Go на гонки данных и проблемы с общим состоянием.
  • Найди горутины, которые могут остаться заблокированными после отмены контекста.
  • Проведи аудит каналов и укажи файл и строку для каждого замечания.

Как установить go-concurrency-review

1Через Skills CLI (Vercel)

npx skills add eduardo-sl/go-agent-skills --skill go-concurrency-review -a claude-code

2Вручную: положить файлы

~/.claude/skills/go-concurrency-review/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/go-concurrency-review/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о go-concurrency-review

Как установить go-concurrency-review в Claude Code?

Выполните npx skills add eduardo-sl/go-agent-skills --skill go-concurrency-review -a claude-code. Файл скилла находится по пути ~/.claude/skills/go-concurrency-review/SKILL.md.

Что делает go-concurrency-review?

Он помогает писать и проверять конкурентный код на Go: анализирует горутины, каналы, синхронизацию и передачу контекста. Для аудита предлагает раздельные проверки жизненного цикла, общего состояния, каналов и контекста.

Что нужно для проверки гонок в go-concurrency-review?

Нужен Go toolchain. Для race detection также требуются cgo и CGO_ENABLED=1.

Исходный текст

SKILL.md · MIT
---
name: go-concurrency-review
description: >
  Review and implement safe concurrency patterns in Go: goroutines,
  channels, sync primitives, context propagation, and goroutine lifecycle
  management. Use when writing concurrent code, reviewing async patterns,
  checking thread safety, debugging race conditions, or designing
  producer/consumer pipelines. Trigger examples: "check thread safety",
  "review goroutines", "race condition", "channel patterns", "sync.Mutex",
  "context cancellation", "goroutine leak".
  Not for: general style (go-coding-standards), HTTP handler patterns
  (go-api-design).
user-invocable: true
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents working on Go projects. Requires the Go toolchain. Race detection requires cgo (CGO_ENABLED=1).
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(gofmt:*)
metadata:
  author: eduardo-sl
  version: "1.8.0"
---

# Go Concurrency Review

Concurrency in Go is powerful and deceptively easy to get wrong.
These patterns prevent goroutine leaks, data races, and deadlocks.

Detailed reference material, loaded on demand:

- `references/channels.md` — sizing, signalling, producer shutdown.
- `references/mutex-and-atomics.md` — mutex placement, lock scope, atomics,
  `sync.Once`, RWMutex pitfalls, `sync.Map`, `sync.Pool`, `singleflight`.
- `references/goroutine-patterns.md` — panic recovery at goroutine
  boundaries, pipelines, bounded fan-out, timers.

Read a reference file only when the section below is not enough.

## Operating Modes

Pick the mode that matches the request before starting:

- **Implementation** — writing new concurrent code. Follow the patterns
  below as construction rules.
- **Diff review** (default) — check changed code against every section,
  paying extra attention to new `go` statements and shared state.
- **Leak/race hunt** — a symptom is already observed (growing goroutine
  count, `-race` report, deadlock). Start from "Auditing Large Codebases"
  and the Race Detection section to localize it. On Go 1.27+ read the
  `goroutineleak` profile first: it lists goroutines blocked on something
  nothing can ever unblock. The go-troubleshooting skill owns the procedure.

## Auditing Large Codebases

For a full concurrency audit, run these independent passes rather than
one linear read:

1. **Goroutine lifecycle:** find every `go` statement
   (`grep -rn "go func\|go [a-zA-Z]" --include="*.go"`) and verify each
   has a termination path (context, closed channel, WaitGroup).
2. **Shared state:** find package-level vars and struct fields accessed
   from multiple goroutines; verify mutex/atomic protection.
3. **Channel topology:** map producers/consumers per channel; verify
   close-exactly-once and no send-on-closed paths.
4. **Context propagation:** verify blocking calls accept and respect
   `context.Context`.

If your environment supports delegating work to parallel sub-agents or
tasks, assign each pass to one; otherwise run them in order. Findings
must cite `file.go:line`. Always finish with `go test -race ./...`.

## Choosing a Primitive

| Need | Use | Why |
|---|---|---|
| Hand data from one goroutine to another | Channel | The send transfers ownership |
| Guard fields of a shared struct | `sync.Mutex` / `RWMutex` | Short critical sections, explicit owner |
| A counter or flag | `atomic.Int64`, `atomic.Bool` | No lock, no torn reads |
| Compute once, read many | `sync.OnceValue` | Exactly once, even under contention |
| Collapse concurrent identical calls | `singleflight.Group` | One backend call per key, not N |
| Reuse short-lived buffers on a hot path | `sync.Pool` | Fewer allocations — only after a profile |

| Waiting for goroutines | Use |
|---|---|
| Results don't fail | `sync.WaitGroup` (`wg.Go`, Go 1.25+) |
| First error matters | `errgroup.Group` |
| First error cancels the rest | `errgroup.WithContext` |
| Cap how many run at once | `errgroup` + `SetLimit(n)` — not a hand-rolled pool |

## 1. Goroutine Lifecycle Management

EVERY goroutine MUST have a clear termination path. No fire-and-forget.

### Use `errgroup` for coordinated goroutines:

```go
g, ctx := errgroup.WithContext(ctx)

g.Go(func() error {
    return fetchUsers(ctx)
})

g.Go(func() error {
    return fetchOrders(ctx)
})

if err := g.Wait(); err != nil {
    return fmt.Errorf("fetch data: %w", err)
}
```

### Long-running goroutines must respect context:

```go
func (w *Worker) Run(ctx context.Context) error {
    for {
        select {
        case <-ctx.Done():
            return ctx.Err()
        case job := <-w.jobs:
            if err := w.process(job); err != nil {
                w.logger.Error("process job", slog.Any("error", err))
            }
        }
    }
}
```

### Start goroutines in the owner, not the callee:

```go
// ✅ Good — caller controls lifecycle
go worker.Run(ctx)

// ❌ Bad — function secretly starts goroutine
func NewWorker() *Worker {
    w := &Worker{}
    go w.run() // hidden goroutine — caller has no control
    return w
}
```

### Recover at the goroutine boundary

A panic in any goroutine terminates the whole process. The `recover` in
HTTP middleware covers the request goroutine only, not goroutines it
starts. Workers and background tasks that run input-dependent or
third-party code recover in their own deferred function, log the stack,
and turn the panic into an error. Don't recover to hide bugs in code you
own — recover where a crash would take unrelated work down with it.
Example: `references/goroutine-patterns.md`.

## 2. Channel Patterns

- Size is one or none. Unbuffered is a synchronization point; buffer 1 is a
  handoff. Any larger buffer needs a comment justifying the number — an
  arbitrary `100` is a bug waiting for the day production is slower than
  staging.
- Signal channels carry `struct{}`, and `close(done)` broadcasts to every
  receiver at once.
- The producer owns the channel and is the only one that closes it, with
  `defer close(ch)` in the producing goroutine. Every send sits in a `select`
  against `ctx.Done()`, or a consumer that walks away leaks the producer.

- Pipelines: each stage closes its own output; fan-out is bounded with
  `errgroup.SetLimit`; a single-goroutine chain is an `iter.Seq`, not
  channels.

Examples in `references/channels.md` and `references/goroutine-patterns.md`.

## 3. Mutexes and Atomics

- Zero-value `sync.Mutex` and `sync.RWMutex` are ready to use. A
  `*sync.Mutex` field is always wrong.
- Declare the mutex directly above the fields it guards, with a comment
  naming the relationship. A mutex that guards "the struct" guards nothing in
  particular.
- Keep the critical section minimal — never call out to an external service,
  or take a second lock, while holding one.
- 🔴 Never copy a value containing a mutex (`c2 := *c1`): the copy carries the
  original's lock state. `go vet` catches most of these; trust it.
- Use `sync/atomic` types for counters and flags rather than a mutex around
  an `int64`.
- `sync.Once` for lazy initialization that must happen exactly once.
- `RWMutex` cannot be upgraded or read-locked recursively; `sync.Map`
  fits two workloads only; `sync.Pool` objects must be reset and size-capped;
  `singleflight` runs on the first caller's context — detach it. Details in
  `references/mutex-and-atomics.md`.

Examples in `references/mutex-and-atomics.md`.

## 4. Context Propagation

Context is always the first parameter, never a struct field, and every
blocking operation selects on `ctx.Done()`:

```go
// ✅ Good
select {
case result := <-ch:
    return result, nil
case <-ctx.Done():
    return nil, ctx.Err()
}

// ❌ Bad — blocks forever if the context is cancelled
result := <-ch
```

Derive a child context with its own timeout for each external call and
`defer cancel()` immediately. Full rules in the `go-context` skill.

## 5. Avoid Mutable Globals

```go
// ❌ Bad — mutable global, not safe for concurrent access
var db *sql.DB

// ✅ Good — pass as dependency
type Server struct {
    db *sql.DB
}
```

## Race Detection

ALWAYS run tests with race detector during CI:

```bash
go test -race ./...
```

This is non-negotiable. A test suite that passes without `-race` proves nothing
about concurrent correctness.

## Red Flags Checklist

- 🔴 Goroutine started without shutdown path
- 🔴 Channel never closed (potential goroutine leak)
- 🔴 Mutex copied by value
- 🔴 Context stored in struct field
- 🔴 `context.Background()` used where parent context was available
- 🔴 `select` without `ctx.Done()` case in blocking operation
- 🔴 Shared map/slice accessed without synchronization
- 🟡 Buffered channel with arbitrary large size
- 🟡 `time.Sleep` used for synchronization instead of proper signaling
- 🟡 Goroutine starting inside `init()` or constructor without lifecycle control
- 🟡 Background goroutine running input-dependent code with no `recover`

© eduardo-sl · MIT · eduardo-sl/go-agent-skills

Похожие скиллы

Все скиллы по теме «Код-ревью и рефакторинг» →
improve-codebase-architecture Matt Pocock Скилл ищет архитектурные узкие места в кодовой базе и показывает варианты углубления модулей в HTML-отчёте. Подойдёт для ревью перед рефакторингом. 1 163 035установок tdd Matt Pocock Скилл управляет циклом красный-зелёный в TDD: проверяет, что тесты пишутся до кода, держит их на уровне публичных интерфейсов и не завязывает на внутреннюю структуру. 1 141 062установок triage Matt Pocock Скилл проводит issue и внешние PR через роли триажа, проверку и подготовку брифа для агента. Подойдёт мейнтейнеру, который разбирает очередь задач. 990 453установок codebase-design Matt Pocock Скилл помогает проектировать модули с небольшим интерфейсом и скрытой внутри сложностью. Подходит для рефакторинга, тестируемости и поиска чистого seam. 850 344установок code-review Matt Pocock Проверяет изменения от выбранной точки по стандартам репозитория и требованиям задачи. Нужен для ревью ветки, PR или незавершённой работы. 789 521установок implement Matt Pocock Выполняет задачу по спецификации или тикетам, ведёт работу через тесты и завершает её ревью с коммитом. Подходит для задач, где нужен дисциплинированный цикл разработки. 774 700установок

Из того же набора22

go-test-quality Скилл помогает писать и проверять тесты Go: от выбора подхода до изоляции сценариев и поиска пробелов в покрытии. Пригодится при доработке тестов и разборе нестабильных проверок. CX Codex +1 ★ 83звёзд репо go-troubleshooting Скилл ведёт агента по диагностике рантайм-проблем в Go: паники, дедлоки, утечки горутин и памяти, отчёты race detector. Пригодится, когда программа падает или висит, а причина неясна. CX Codex +1 ★ 83звёзд репо go-performance-review Скилл ищет узкие места в Go-коде и помогает проверять оптимизации бенчмарками и профилями. Пригодится для ревью горячих путей и снижения аллокаций. CX Codex +1 ★ 83звёзд репо go-observability Скилл для Go-сервисов: помогает настроить структурные логи на log/slog, трейсы и метрики через OpenTelemetry, а также алерты по SLO. Пригодится, когда сервис уже в проде и нужно видеть, что в нём происходит. CX Codex +1 ★ 83звёзд репо go-modernize Скилл помогает применять современные возможности Go и стандартной библиотеки. Пригодится для точечных правок или модернизации пакета и модуля. CX Codex +1 ★ 83звёзд репо go-error-handling Скилл задаёт агенту правила работы с ошибками в Go: обёртка через %w, sentinel-ошибки, свои типы и errors.Is/errors.As. CX Codex +1 ★ 83звёзд репо go-data-structures Скилл помогает выбирать и безопасно использовать слайсы, карты и массивы в Go. Пригодится, когда нужно разобраться с append, nil-слайсами или порядком обхода карты. CX Codex +1 ★ 83звёзд репо go-context Скилл для ИИ-агента, который проверяет и правит работу с context.Context в Go: отмена, таймауты, значения, типичные ошибки. CX Codex +1 ★ 83звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой