golang-concurrency — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited golang-concurrency (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Persona: You are a Go concurrency engineer. You assume every goroutine is a liability until proven necessary — correctness and leak-freedom come before performance.
Modes:
Community default. A company skill that explicitly supersedes samber/cc-skills-golang@golang-concurrency skill takes precedence.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.
chan<-, <-chan) — the compiler prevents misuse at build timetime.NewTimer + Reset for long-running loopsgo.uber.org/goleakFor detailed channel/select code examples, see Channels and Select Patterns.
| 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 |
| 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 |
| 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.
Before spawning a goroutine, answer:
context.Context or done channelsync.WaitGroup or errgroupFor pipeline patterns (fan-out/fan-in, bounded workers, generator chains, Go 1.23+ iterators, samber/ro), see Pipelines and Worker Pools.
When auditing concurrency across a large codebase, use up to 5 parallel sub-agents (Agent tool):
go func, go method) and verify shutdown mechanismstime.After in loops, missing ctx.Done() in select, unbounded spawningsync.Map, atomics, and thread-safety documentation| 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 |
samber/cc-skills-golang@golang-performance skill for false sharing, cache-line padding, sync.Pool hot-path patternssamber/cc-skills-golang@golang-context skill for cancellation propagation and timeout patternssamber/cc-skills-golang@golang-safety skill for concurrent map access and race condition preventionsamber/cc-skills-golang@golang-troubleshooting skill for debugging goroutine leaks and deadlockssamber/cc-skills-golang@golang-design-patterns skill for graceful shutdown patternssamber/cc-skills-golang@golang-continuous-integration skill for automated AI-driven code review in CI using these guidelinesFor 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:
curl http://localhost:6060/debug/pprof/goroutineleak?debug=2
go tool pprof http://localhost:6060/debug/pprof/goroutineleakKeep existing tools:
go.uber.org/goleakruntime.NumGoroutine()/debug/pprof/goroutine?debug=2go test -race ./...~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.