From go-toolkit
Implements Go concurrency patterns like worker pools, pipelines, channels, select, mutexes, and RWMutex for parallel processing and goroutine management.
How this skill is triggered — by the user, by Claude, or both
Slash command
/go-toolkit:goroutine-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement Go concurrency patterns for efficient parallel processing.
Implement Go concurrency patterns for efficient parallel processing.
Basic goroutine:
go func() {
// Runs concurrently
}()
With channel:
ch := make(chan int)
go func() {
ch <- 42
}()
result := <-ch
Simple parallel execution:
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
process(id)
}(i)
}
wg.Wait()
Worker pool:
jobs := make(chan Job, 100)
results := make(chan Result, 100)
// Start workers
for w := 0; w < numWorkers; w++ {
go worker(jobs, results)
}
// Send jobs
for _, job := range allJobs {
jobs <- job
}
close(jobs)
// Collect results
for range allJobs {
result := <-results
handleResult(result)
}
Pipeline:
// Stage 1: Generate
gen := func() <-chan int {
out := make(chan int)
go func() {
defer close(out)
for i := 0; i < 10; i++ {
out <- i
}
}()
return out
}
// Stage 2: Process
process := func(in <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for n := range in {
out <- n * 2
}
}()
return out
}
// Use pipeline
for result := range process(gen()) {
fmt.Println(result)
}
Unbuffered channel (synchronous):
ch := make(chan int)
go func() {
ch <- 42 // Blocks until received
}()
value := <-ch // Blocks until sent
Buffered channel (asynchronous):
ch := make(chan int, 10) // Buffer of 10
ch <- 1 // Doesn't block until buffer full
ch <- 2
value := <-ch // Doesn't block if buffer has data
Select for multiple channels:
select {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case msg := <-ch2:
fmt.Println("Received from ch2:", msg)
case <-time.After(time.Second):
fmt.Println("Timeout")
}
Mutex for shared state:
type SafeCounter struct {
mu sync.Mutex
count int
}
func (c *SafeCounter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func (c *SafeCounter) Value() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
RWMutex for read-heavy workloads:
type Cache struct {
mu sync.RWMutex
items map[string]string
}
func (c *Cache) Get(key string) (string, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
val, ok := c.items[key]
return val, ok
}
func (c *Cache) Set(key, value string) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = value
}
WaitGroup for goroutine coordination:
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
doWork(id)
}(i)
}
wg.Wait() // Wait for all goroutines
Basic context usage:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
for {
select {
case <-ctx.Done():
return // Exit when cancelled
default:
doWork()
}
}
}()
// Cancel when done
cancel()
With timeout:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := doWorkWithContext(ctx)
if err == context.DeadlineExceeded {
fmt.Println("Operation timed out")
}
Propagate context:
func ProcessRequest(ctx context.Context, req Request) error {
// Pass context to all operations
data, err := fetchData(ctx, req.ID)
if err != nil {
return err
}
return saveData(ctx, data)
}
func fanOut(in <-chan int, n int) []<-chan int {
outs := make([]<-chan int, n)
for i := 0; i < n; i++ {
outs[i] = process(in)
}
return outs
}
func fanIn(channels ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, ch := range channels {
wg.Add(1)
go func(c <-chan int) {
defer wg.Done()
for n := range c {
out <- n
}
}(ch)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
func rateLimiter(rate time.Duration) <-chan time.Time {
return time.Tick(rate)
}
limiter := rateLimiter(time.Second / 10) // 10 per second
for range limiter {
go processItem()
}
func doWithTimeout(timeout time.Duration) error {
done := make(chan error, 1)
go func() {
done <- doWork()
}()
select {
case err := <-done:
return err
case <-time.After(timeout):
return errors.New("timeout")
}
}
import "golang.org/x/sync/errgroup"
func processAll(items []Item) error {
g := new(errgroup.Group)
for _, item := range items {
item := item // Capture for goroutine
g.Go(func() error {
return process(item)
})
}
return g.Wait() // Returns first error
}
For detailed patterns:
Goroutine leaks:
Deadlocks:
Race conditions:
go run -race to detectPerformance issues:
val, ok := <-chnpx claudepluginhub p/armanzeroeight-go-toolkit-plugins-go-toolkitProvides code examples for Go goroutines, channels (unbuffered, buffered, directional, closing), select statements, and sync patterns when writing concurrent Go code.
Master Go concurrency with goroutines, channels, sync primitives, and context. Use when building concurrent Go applications, implementing worker pools, or debugging race conditions.
Provides Go concurrency patterns for goroutines, channels, sync primitives, and context. Useful for concurrent applications, worker pools, and debugging race conditions.