Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cxuu avatar

Go Concurrency

  • 924 installs
  • 137 repo stars
  • Updated June 20, 2026
  • cxuu/golang-skills

go-concurrency is a Claude Code skill that teaches Go developers advanced concurrency patterns from Effective Go for request multiplexing, reply channels, and CPU-bound parallelization without race conditions.

About

go-concurrency is an advanced Go reference skill grounded in Effective Go for situational concurrency patterns beyond basic goroutines. It explains channels of channels, embedding reply channels inside request structs, and patterns for multiplexing many clients through shared workers while keeping responses routed correctly. The skill emphasizes when to use each pattern for request/response fan-in and CPU-bound parallelization instead of reaching for mutexes by default. Backend and systems developers reach for go-concurrency when a Go service must coordinate many concurrent callers, route replies safely, or scale CPU work across goroutines without introducing data races.

  • Channels-of-channels pattern for non-blocking RPC with per-request reply channels
  • CPU-bound parallelization using sync.WaitGroup across multiple cores
  • Reference implementations directly from Effective Go, modernized for current Go
  • Situational patterns: apply only when you need request/response multiplexing or true parallelism

Go Concurrency by the numbers

  • 924 all-time installs (skills.sh)
  • +39 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #427 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cxuu/golang-skills --skill go-concurrency

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs924
repo stars137
Security audit3 / 3 scanners passed
Last updatedJune 20, 2026
Repositorycxuu/golang-skills

How do you multiplex Go requests with reply channels?

Correctly implement request multiplexing, reply channels, and CPU-bound parallelization in Go services without introducing mutexes or race conditions.

Who is it for?

Go backend developers implementing high-concurrency services who need Effective Go patterns for reply channels and worker multiplexing.

Skip if: Beginners learning basic goroutines and channels who have not yet hit request routing or CPU-bound scaling problems.

When should I use this skill?

User asks about Go channels of channels, reply channels, request multiplexing, CPU-bound parallelization, or Effective Go concurrency.

What you get

Go concurrency patterns with reply-channel request structs, multiplexed workers, and race-free CPU parallelization guidance.

  • Reply-channel request structs
  • Multiplexed worker patterns
  • Concurrency design notes

Files

SKILL.mdMarkdownGitHub ↗

Go Concurrency

Compatibility: Atomic examples may use standard-library typed atomics where available or go.uber.org/atomic where a project already depends on it.

Resource Routing

  • references/GOROUTINE-PATTERNS.md - Read when starting, stopping, or waiting for goroutines.
  • references/SYNC-PRIMITIVES.md - Read when choosing between mutexes, atomics, channels, and once-like primitives.
  • references/BUFFER-POOLING.md - Read when considering channel-backed or sync.Pool-style reuse.
  • references/ADVANCED-PATTERNS.md - Read for worker pools, pipelines, errgroup, and cancellation-heavy patterns.

Goroutine Lifetimes

Normative: When you spawn goroutines, make it clear when or whether they
exit.

Goroutines can leak by blocking on channel sends/receives. The GC will not terminate a blocked goroutine even if no other goroutine holds a reference to the channel. Even non-leaking in-flight goroutines cause panics (send on closed channel), data races, memory issues, and resource leaks.

Core Rules

1. Every goroutine needs a stop mechanism — a predictable end time, a cancellation signal, or both 2. Code must be able to wait for the goroutine to finish 3. No goroutines in `init()` — expose lifecycle methods (Close, Stop, Shutdown) instead 4. Keep synchronization scoped — constrain to function scope, factor logic into synchronous functions

// Good: Clear lifetime with WaitGroup.Go (Go 1.25+)
var wg sync.WaitGroup
for item := range queue {
    item := item
    wg.Go(func() { process(ctx, item) })
}
wg.Wait()
// Bad: No way to stop or wait
go func() { for { flush(); time.Sleep(delay) } }()

Test for leaks with go.uber.org/goleak.

Principle: Never start a goroutine without knowing how it will stop.

---

Share by Communicating

"Do not communicate by sharing memory; instead, share memory by communicating."

This is Go's foundational concurrency design principle. Use channels for ownership transfer and orchestration — when one goroutine produces a value and another consumes it. Use mutexes when multiple goroutines access shared state and channels would add unnecessary complexity.

Default to channels. Fall back to sync.Mutex / sync.RWMutex when the problem is naturally about protecting a shared data structure (e.g., a cache or counter) rather than passing data between goroutines.

---

Synchronous Functions

Normative: Prefer synchronous functions over asynchronous ones.
BenefitWhy
Localized goroutinesLifetimes easier to reason about
Avoids leaks and racesEasier to prevent resource leaks and data races
Easier to testCheck input/output without polling
Caller flexibilityCaller adds concurrency when needed
Advisory: It is quite difficult (sometimes impossible) to remove
unnecessary concurrency at the caller side. Let the caller add concurrency
when needed.

---

Zero-value Mutexes

The zero-value of sync.Mutex and sync.RWMutex is valid — almost never need a pointer to a mutex.

// Good: Zero-value is valid    // Bad: Unnecessary pointer
var mu sync.Mutex                mu := new(sync.Mutex)

Don't embed mutexes — use a named mu field to keep Lock/Unlock as implementation details, not exported API.

---

Channel Direction

Normative: Specify channel direction where possible.

Direction prevents errors (compiler catches closing a receive-only channel), conveys ownership, and is self-documenting.

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

Channel Size: One or None

Channels should have size zero (unbuffered) or one. Any other size requires justification for:

  • How the size was determined
  • What prevents the channel from filling under load
  • What happens when writers block
c := make(chan int)    // unbuffered — Good
c := make(chan int, 1) // size one — Good
c := make(chan int, 64) // arbitrary — needs justification

---

Atomic Operations

Use atomic.Bool, atomic.Int64, etc. (stdlib sync/atomic since Go 1.19, or go.uber.org/atomic) for type-safe atomic operations. Raw int32/int64 fields make it easy to forget atomic access on some code paths.

// Good: Type-safe              // Bad: Easy to forget
var running atomic.Bool          var running int32 // atomic
running.Store(true)              atomic.StoreInt32(&running, 1)
running.Load()                   running == 1 // race!

---

Documenting Concurrency

Advisory: Document thread-safety when it's not obvious from the operation
type.

Go users assume read-only operations are safe for concurrent use, and mutating operations are not. Document concurrency when:

1. Read vs mutating is unclear — e.g., a Lookup that mutates LRU state 2. API provides synchronization — e.g., thread-safe clients 3. Interface has concurrency requirements — document in type definition

---

Context Usage

For context.Context guidance (parameter placement, struct storage, custom
types, derivation patterns), see the dedicated
go-context skill.

---

Buffer Pooling with Channels

Use a buffered channel as a free list to reuse allocated buffers. This "leaky buffer" pattern uses select with default for non-blocking operations.

---

Related Skills

  • Context propagation: See go-context when passing cancellation, deadlines, or request-scoped values through goroutines
  • Error handling: See go-error-handling when propagating errors from goroutines or using errgroup
  • Defensive hardening: See go-defensive when protecting shared state at API boundaries or using defer for cleanup
  • Interface design: See go-interfaces when choosing receiver types for types with sync primitives

External Resources

  • [Never start a goroutine without knowing how it will

stop](https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop) — Dave Cheney

  • [Rethinking Classical Concurrency

Patterns](https://www.youtube.com/watch?v=5zXAHh5tJqQ) — Bryan Mills (GopherCon 2018)

detector for testing

atomic operations

Related skills

How it compares

Pick go-concurrency when you need Effective Go multiplexing and reply-channel architectures rather than introductory goroutine tutorials.

FAQ

What Go patterns does go-concurrency cover?

go-concurrency covers advanced Effective Go patterns including channels of channels, reply channels embedded in request structs, and CPU-bound parallelization. These patterns help route responses per client and scale worker pools without unnecessary mutex usage.

When should I use go-concurrency instead of basic goroutine guides?

go-concurrency fits when a Go service needs request/response multiplexing or CPU-bound parallelization beyond starter goroutine examples. The skill is situational and assumes familiarity with basic channels before applying reply-channel architectures.

Is Go Concurrency safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Backend & APIsbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.