Przejdź do treści
Biblioteka skilli
Programowanie · Budowanie i kod

go-concurrency

/go-concurrency

Pomaga pisać i recenzować współbieżny kod Go: goroutines, kanały, select, mutexy, atomics, errgroup, singleflight, pule workerów i potoki fan-out i fan-in.

Repozytorium
gophers ↗
Licencja
MIT
Ostatnia zmiana repozytorium
11.08.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
6
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
1
Przestarzałość

Brak sygnałów. Repozytorium zmienione 11.08.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Pomaga pisać i recenzować współbieżny kod Go: goroutines, kanały, select, mutexy, atomics, errgroup, singleflight, pule workerów i potoki fan-out i fan-in.

Oryginalny opis (EN)

Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker pools, or fan-out/fan-in pipelines. Apply proactively whenever a goroutine is spawned, a shared field is mutated, or a channel is created, even if the user has not asked about concurrency. Does not cover context.Context patterns (see go-context).

Jak działa

  1. Core Rules
  2. Primitive Decision
  3. Goroutine Lifetimes
  4. errgroup: Errors and Cancellation
  5. Channels
  6. Mutexes and Atomics
  7. Testing: goleak and synctest
  8. Anti-Patterns
  9. Verification Checklist
  10. References
Sekcje z nagłówków SKILL.md, w oryginale · 123 linii, 1 041 słów
Podgląd SKILL.md
---
name: go-concurrency
description: "Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker pools, or fan-out/fan-in pipelines. Apply proactively whenever a goroutine is spawned, a shared field is mutated, or a channel is created, even if the user has not asked about concurrency. Does not cover context.Context patterns (see go-context)."
license: MIT
compatibility: "Designed for Claude Code or similar AI coding agents. Targets Go 1.21+ for typed atomics and slog. Notes Go 1.25 wg.Go, Go 1.26 testing/synctest, and Go 1.26 experimental goroutineleak profile where relevant."
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)
---

# Go Concurrency

Goroutines are cheap, but every one you spawn is a resource you must own. The goal is **structured concurrency**: each goroutine has a clear owner, a predictable exit, and a way for the caller to wait and collect errors.

## Core Rules

1. **Never start a goroutine without knowing how it will stop.** A blocked goroutine is not garbage-collected — it leaks.
2. **The caller must be able to wait.** Use `sync.WaitGroup`, `errgroup.Group`, or an explicit done channel.
3. **No goroutines in `init()`.** Expose `Start`/`Stop`/`Shutdown` so callers control the lifecycle.
4. **Share by communicating.** Default to channels; reach for `sync.Mutex` only when the problem is genuinely "protect a shared field".
5. **Only the sender closes a channel.** Closing from the receiver side panics on the next send.
6. **Specify channel direction** (`chan<-`, `<-chan`) at function boundaries — the compiler catches misuse.
7. **Always include `ctx.Done()` in `select`.** Without it, the goroutine cannot be cancelled.
8. **Test for leaks** with [`go.uber.org/goleak`](https://pkg.go.dev/go.uber.org/goleak).

## Primitive Decision

| Need | Use | Why |
|---|---|---|
| Pass a value from producer to consumer | Channel | Transfers ownership explicitly |
| Wait for N fire-and-forget goroutines | `sync.WaitGroup` (Go 1.25: `wg.Go`) | No error needed |
| Wait + collect first error + cancel siblings | `errgroup.WithContext` | Structured failure |
| Bound concurrency (worker pool) | `errgroup.SetLimit(n)` | Replaces hand-rolled pools |
| Protect a shared field | `sync.Mutex` / `sync.RWMutex` | Short critical section |
| Counter / flag | typed `sync/atomic` (`atomic.Int64`, `atomic.Bool`) | Lock-free, type-safe |
| Read-heavy concurrent map | `sync.Map` | Concurrent map read/write otherwise crashes |
| One-shot init | `sync.Once` (or `OnceFunc`/`OnceValue` in 1.21+) | Idempotent setup |
| Deduplicate concurrent calls | `x/sync/singleflight` | Cache stampede prevention |

> Read [references/sync-primitives.md](references/sync-primitives.md) when picking between mutex, atomic, `sync.Map`, `sync.Pool`, or `singleflight`, or when designing the field layout of a struct that protects shared state.

## Goroutine Lifetimes

```go
// Good: bounded WaitGroup, deterministic exit
var wg sync.WaitGroup
for item := range queue {
    wg.Add(1)
    go func(it Item) { defer wg.Done(); process(ctx, it) }(item)
}
wg.Wait()

// Bad: no stop signal, no wait — classic leak
go func() { for { flush(); time.Sleep(delay) } }()
```

Go 1.25+ exposes `wg.Go(fn)` which folds `Add`/`Done` into one call. Always call `wg.Add` **before** `go` — otherwise `wg.Wait` may return before the goroutine even starts.

## errgroup: Errors and Cancellation

`errgroup.WithContext` is the right default when sibling goroutines should cancel each other on the first failure:

```go
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(8)
for _, url := range urls {
    g.Go(func() error { return fetch(ctx, url) })
}
if err := g.Wait(); err != nil {
    return fmt.Errorf("fetching urls: %w", err)
}
```

`g.Wait` returns the first non-nil error; `ctx` is cancelled as soon as any worker fails. See [references/errgroup-and-pools.md](references/errgroup-and-pools.md).

## Channels

```go
func produce(out chan<- int)                  { /* send-only */ }
func consume(in <-chan int)                   { /* receive-only */ }
func transform(in <-chan int, out chan<- int) { /* ownership crosses */ }
```

**Buffer size is `0` or `1`.** Anything larger must be justified (what bounds it under load, what happens when writers block).

In every long-running `select`, include `<-ctx.Done()`. Avoid `time.After` in hot loops — it allocates a timer per iteration; hoist a `time.NewTimer` and `Reset` it instead.

> Read [references/channels-and-select.md](references/channels-and-select.md) when implementing pipelines, fan-in/fan-out, broadcast via `close`, or non-blocking sends with `default`.

## Mutexes and Atomics

The zero value of `sync.Mutex`/`RWMutex` is valid — almost never use a pointer. Do not embed mutexes; keep them as an unexported `mu` field so `Lock`/`Unlock` aren't public API. Keep critical sections short; never hold a lock across I/O. Prefer typed atomics (`atomic.Bool`, `atomic.Int64`) over raw `sync/atomic` on `int32`/`int64` fields.

## Testing: goleak and synctest

Wire `go.uber.org/goleak` into every package that spawns goroutines (`goleak.VerifyTestMain(m)` or `defer goleak.VerifyNone(t)`). For timer-dependent tests, use `testing/synctest` (Go 1.25+) so synthetic time advances deterministically. Go 1.26 adds an experimental `goroutineleak` pprof profile for production diagnosis — it is not a substitute for `goleak` in tests. See [references/leaks-and-synctest.md](references/leaks-and-synctest.md).

## Anti-Patterns

| Anti-pattern | Why it hurts | Do this instead |
|---|---|---|
| Fire-and-forget `go func()` with no signal | Leaks on shutdown; can outlive its inputs | Pass `ctx`, use `errgroup`, or own a done channel |
| Closing a channel from the receiver | Panics on the next send | Only the sender closes |
| `time.After` in a hot loop | Allocates a timer per iteration | `time.NewTimer` + `Reset` |
| `select` without `ctx.Done()` | Cannot be cancelled | Always include the cancel case |
| `wg.Add(1)` inside the goroutine | `Wait` may return before `Add` runs | `Add` before `go`, or use `wg.Go` (Go 1.25+) |
| Buffered channel sized "to be safe" | Hides backpressure, masks bugs | Size 0 or 1; justify anything larger |
| Concurrent read+write on `map` | Hard runtime crash, not a race warning | `sync.Map` or `sync.RWMutex` + map |
| Mutex held across I/O / RPC | Serializes the whole service | Copy what you need under the lock; release before the call |
| Sending a pointer through a channel | Re-introduces shared memory | Send a copy or an immutable value |
| Forgetting `-race` in CI | Races ship to prod | `go test -race ./...` always |

## Verification Checklist

Before finishing a concurrency change:

- [ ] Every `go` has a documented exit (ctx, done channel, or bounded loop)
- [ ] Every long-running `select` has a `<-ctx.Done()` case
- [ ] `wg.Add` is called before `go`, or `wg.Go` is used (Go 1.25+)
- [ ] Channels are sized 0 or 1, or the size has a comment justifying it
- [ ] Only the sender closes channels; receivers use `for v := range ch` or `v, ok := <-ch`
- [ ] No mutex is held across network/disk I/O
- [ ] `go test -race ./...` is clean
- [ ] Packages that spawn goroutines wire `goleak.VerifyTestMain` or per-test `VerifyNone`

## References

- [references/sync-primitives.md](references/sync-primitives.md) — mutex vs atomic vs `sync.Map`/`Pool`/`Once`/`singleflight`
- [references/channels-and-select.md](references/channels-and-select.md) — channel ownership, direction, pipelines, non-blocking sends
- [references/errgroup-and-pools.md](references/errgroup-and-pools.md) — `errgroup`, `SetLimit`, worker pools, fan-out/fan-in
- [references/leaks-and-synctest.md](references/leaks-and-synctest.md) — `goleak`, `testing/synctest`, Go 1.26 experimental leak profile
Pliki w paczce (6)
  • SKILL.md 8 KB
  • agents/openai.yaml 1 KB
  • references/channels-and-select.md 3 KB
  • references/errgroup-and-pools.md 4 KB
  • references/leaks-and-synctest.md 4 KB
  • references/sync-primitives.md 3 KB

Wersje

RepozytoriumWynikLicencja
Ta strona · muratmirgun/gophers100MIT
h0rn3t/golang-skills100Apache-2.0
fusengine/agents100MIT
muratmirgun/gophers100MIT
cxuu/golang-skills100Apache-2.0
TheBushidoCollective/han95Apache-2.0
Amey-Thakur/AI-SKILLS90MIT

Migawka bazy z 28.10.2026 · wersja paczki 857f981118e1 (skrót SHA-256 całej paczki)

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100golang-concurrency
    Dostarcza zasady współbieżności w Go: cykl życia goroutine i wycieki, kanały i select, mutexy, atomiki, errgroup, singleflight, pule workerów oraz wzorce fan-out i fan-in.
  • 100golang-concurrency
    Pisze bezpieczny współbieżny kod Go z goroutines, kanałami i context.
  • 100go-concurrency-patterns
    Uczy współbieżności w Go: goroutines, kanały, prymitywy sync i context, przy budowie aplikacji, worker pools i diagnozowaniu wyścigów danych.
  • 100go-concurrency-patterns
    Uczy współbieżności w Go: goroutines, kanały, prymitywy sync i context, przy budowie aplikacji, worker pools i diagnozowaniu wyścigów danych.
  • 100go-concurrency-review
    Recenzuje i wdraża bezpieczne wzorce współbieżności w Go: goroutines, kanały, prymitywy sync, propagacja kontekstu, cykl życia goroutines, wyścigi danych i potoki producent-konsument.
  • 100go-concurrency-practice
    Egzekwuje praktyczne reguły współbieżności w Go z książki „100 Go Mistakes” przy pisaniu i przeglądzie kodu: propagację context, wycieki goroutines, wyścigi danych i deadlocki.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.