All skills
cxuu avatar

/go-concurrency

@91f0c2e
by Charles Xucxuu/golang-skills165 stars
19

Use when writing concurrent Go code — goroutines, channels, mutexes, or thread-safety guarantees. Also use when parallelizing work, fixing data races, or protecting shared state, even if the user doesn't explicitly mention concurrency primitives. Does not cover context.Context patterns (see go-context).

Use this Skill: https://skilld.dev/gh/cxuu/golang-skills/go-concurrency

This session only. Nothing lands on disk.

referencesADVANCED-PATTERNS.md

≈876 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Advanced Concurrency Patterns

Detailed reference for advanced concurrency patterns from Effective Go. These patterns are situational — use when you need request/response multiplexing or CPU-bound parallelization.


Channels of Channels

Source: Effective Go

A channel is a first-class value that can be allocated and passed around like any other. A powerful pattern is embedding a reply channel inside a request struct, letting each client provide its own path for the answer:

type Request struct {
    args       []int
    f          func([]int) int
    resultChan chan int
}

The client sends a request with a function, its arguments, and a channel on which to receive the result:

request := &Request{[]int{3, 4, 5}, sum, make(chan int)}
clientRequests <- request
fmt.Printf("answer: %d\n", <-request.resultChan)

The server handler reads from the queue and sends results back on each request's reply channel:

func handle(queue chan *Request) {
    for req := range queue {
        req.resultChan <- req.f(req.args)
    }
}

This pattern forms the basis for a rate-limited, parallel, non-blocking RPC system without a mutex in sight.


CPU-Bound Parallelization

Source: Effective Go (modernized)

When a computation can be broken into independent pieces, parallelize it across CPU cores using a sync.WaitGroup to wait for completion. On Go 1.25 and newer, use WaitGroup.Go so the add/done bookkeeping stays coupled to the goroutine:

type Vector []float64

func (v Vector) DoSome(i, n int, u Vector) {
    for ; i < n; i++ {
        v[i] += u.Op(v[i])
    }
}

func (v Vector) DoAll(u Vector) {
    numCPU := runtime.NumCPU()
    var wg sync.WaitGroup
    for i := 0; i < numCPU; i++ {
        i := i
        wg.Go(func() {
            v.DoSome(i*len(v)/numCPU, (i+1)*len(v)/numCPU, u)
        })
    }
    wg.Wait()
}

Use runtime.NumCPU() for hardware cores or runtime.GOMAXPROCS(0) to honor the user's resource configuration. For Go versions before 1.25, use wg.Add(1), go func, and defer wg.Done() around each launched goroutine.

Important: Don't confuse concurrency (structuring a program as independently executing components) with parallelism (executing calculations simultaneously on multiple CPUs). Go is a concurrent language; not all parallelization problems fit its model.


Common Mistakes

Forgetting to signal completion

If a goroutine never calls wg.Done() (or never sends on a done channel), the waiting goroutine blocks forever:

// Bad: Missing wg.Done — deadlocks
var wg sync.WaitGroup
wg.Add(1)
go func() {
    doWork()
}()
wg.Wait()

// Good: Always defer wg.Done
var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    doWork()
}()
wg.Wait()

Unbounded goroutine spawning

Launching one goroutine per work item with no limit can exhaust memory or overwhelm downstream resources. Use a semaphore to cap concurrency:

// Bad: Spawns len(items) goroutines at once
var wg sync.WaitGroup
for _, item := range items {
    wg.Add(1)
    go func(it Item) {
        defer wg.Done()
        process(it)
    }(item)
}
wg.Wait()

// Good: Semaphore limits concurrency to maxWorkers
var wg sync.WaitGroup
sem := make(chan struct{}, maxWorkers)
for _, item := range items {
    wg.Add(1)
    sem <- struct{}{}
    go func(it Item) {
        defer wg.Done()
        defer func() { <-sem }()
        process(it)
    }(item)
}
wg.Wait()

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill provides comprehensive guidelines and best practices for writing concurrent Go code, focusing on goroutine lifetimes, channel patterns, and synchronization primitives. It includes references to trusted community resources and tools. No security issues were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    2 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 91f0c2e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago

README badge

README badge for cxuu/golang-skills/go-concurrency