go-concurrency

pluginagentmarketplace's avatarfrom pluginagentmarketplace

Go concurrency patterns - goroutines, channels, sync primitives

⭐1stars🔀0forks📁View on GitHub🕐Updated Dec 31, 2025

When & Why to Use This Skill

This Claude skill provides production-ready Go concurrency patterns, enabling developers to build high-performance, thread-safe applications. It covers essential Golang primitives including goroutines, channels, and sync packages, offering optimized templates for worker pools, rate limiters, and resilient retry logic to solve complex parallel programming challenges.

Use Cases

  • Architecting high-throughput data processing pipelines using worker pool and fan-out/fan-in patterns to maximize CPU utilization.
  • Implementing thread-safe state management in concurrent applications using RWMutex and atomic operations to prevent data races.
  • Designing resilient microservices with context-aware goroutine management and exponential backoff retry strategies for distributed systems.
  • Building sophisticated rate-limiting mechanisms to protect downstream APIs and manage resource consumption effectively.
  • Debugging and resolving common concurrency pitfalls such as deadlocks, goroutine leaks, and synchronization bottlenecks in existing Go codebases.
namego-concurrency
descriptionGo concurrency patterns - goroutines, channels, sync primitives
sasmp_version"1.3.0"
bonded_agent02-go-concurrency
bond_typePRIMARY_BOND

Go Concurrency Skill

Master Go concurrency patterns for safe, efficient parallel programming.

Overview

Production-ready concurrency patterns including goroutines, channels, sync primitives, and common pitfalls to avoid.

Parameters

Parameter Type Required Default Description
pattern string yes - Pattern: "worker-pool", "fan-out", "pipeline", "semaphore"
workers int no runtime.NumCPU() Number of concurrent workers
buffer_size int no 0 Channel buffer size

Core Topics

Goroutines with Context

func ProcessItems(ctx context.Context, items []Item) error {
    g, ctx := errgroup.WithContext(ctx)

    for _, item := range items {
        item := item // capture loop variable
        g.Go(func() error {
            select {
            case <-ctx.Done():
                return ctx.Err()
            default:
                return process(item)
            }
        })
    }

    return g.Wait()
}

Worker Pool

func WorkerPool[T, R any](ctx context.Context, workers int, jobs <-chan T, fn func(T) R) <-chan R {
    results := make(chan R, workers)

    var wg sync.WaitGroup
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                select {
                case <-ctx.Done():
                    return
                case job, ok := <-jobs:
                    if !ok {
                        return
                    }
                    results <- fn(job)
                }
            }
        }()
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    return results
}

Rate Limiter

type RateLimiter struct {
    tokens chan struct{}
}

func NewRateLimiter(rate int, interval time.Duration) *RateLimiter {
    rl := &RateLimiter{
        tokens: make(chan struct{}, rate),
    }

    go func() {
        ticker := time.NewTicker(interval / time.Duration(rate))
        defer ticker.Stop()
        for range ticker.C {
            select {
            case rl.tokens <- struct{}{}:
            default:
            }
        }
    }()

    return rl
}

func (rl *RateLimiter) Wait(ctx context.Context) error {
    select {
    case <-ctx.Done():
        return ctx.Err()
    case <-rl.tokens:
        return nil
    }
}

Mutex Patterns

type SafeCounter struct {
    mu    sync.RWMutex
    count map[string]int
}

func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.count[key]++
}

func (c *SafeCounter) Get(key string) int {
    c.mu.RLock()
    defer c.mu.RUnlock()
    return c.count[key]
}

Retry Logic

func RetryWithBackoff(ctx context.Context, fn func() error) error {
    backoff := []time.Duration{
        100 * time.Millisecond,
        500 * time.Millisecond,
        2 * time.Second,
        5 * time.Second,
    }

    var lastErr error
    for i, delay := range backoff {
        if err := fn(); err != nil {
            lastErr = err
            select {
            case <-ctx.Done():
                return ctx.Err()
            case <-time.After(delay):
                continue
            }
        }
        return nil
    }
    return fmt.Errorf("max retries exceeded: %w", lastErr)
}

Unit Test Template

func TestWorkerPool(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    jobs := make(chan int, 10)
    for i := 0; i < 10; i++ {
        jobs <- i
    }
    close(jobs)

    results := WorkerPool(ctx, 3, jobs, func(n int) int {
        return n * 2
    })

    var sum int
    for r := range results {
        sum += r
    }

    expected := 90 // sum of 0*2 + 1*2 + ... + 9*2
    if sum != expected {
        t.Errorf("got %d, want %d", sum, expected)
    }
}

Troubleshooting

Failure Modes

Symptom Cause Fix
deadlock! Blocked channel Add buffer or close properly
DATA RACE Shared state Use mutex or channel
Goroutine leak Missing close/cancel Always use context
send on closed Multiple closers Single owner pattern

Debug Commands

go test -race -v ./...
go build -race -o app ./cmd/api
GODEBUG=gctrace=1 ./app  # GC tracing

Usage

Skill("go-concurrency")