npx claudepluginhub jamesprial/prial-plugins --plugin golang-workflowThis skill uses the workspace's default tool permissions.
Every goroutine must have a way to exit. Use channels or context for shutdown signals.
Reviews and implements safe Go concurrency patterns: goroutines, channels, sync primitives, context propagation, lifecycle management. Use for thread safety checks, race debugging, producer/consumer pipelines.
Guides Go concurrency: goroutine lifetimes with WaitGroups, channels for communication, mutexes for shared state, preventing leaks and data races.
Guides writing, reviewing, and auditing concurrent Go code using goroutines, channels, select, locks, sync primitives, errgroup, singleflight, and worker pools. Detects leaks, races, and ownership issues.
Share bugs, ideas, or general feedback.
Every goroutine must have a way to exit. Use channels or context for shutdown signals.
type Worker struct {
done chan struct{}
}
func (w *Worker) Start() {
w.done = make(chan struct{})
go func() {
for {
select {
case <-w.done:
return
case <-time.After(1 * time.Second):
// do work
}
}
}()
}
func (w *Worker) Stop() {
close(w.done)
}
func StartWorker(ctx context.Context) {
go func() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
// do work
}
}
}()
}
func StartWorker() {
go func() {
for {
// Runs forever - goroutine leak!
time.Sleep(1 * time.Second)
// do work
}
}()
}
func GetData() string {
ch := make(chan string)
go func() {
ch <- fetchData() // Blocks forever if nobody reads
}()
// If timeout happens, goroutine leaks
select {
case result := <-ch:
return result
case <-time.After(1 * time.Second):
return "timeout"
}
}
func GetData() string {
ch := make(chan string, 1) // Buffer size 1
go func() {
ch <- fetchData() // Won't block
}()
select {
case result := <-ch:
return result
case <-time.After(1 * time.Second):
return "timeout"
}
}
go func() needs an exit conditionselect with ctx.Done() or done channelruntime.NumGoroutine() to detect leaksfunc TestNoLeaks(t *testing.T) {
before := runtime.NumGoroutine()
worker := NewWorker()
worker.Start()
worker.Stop()
time.Sleep(100 * time.Millisecond) // Allow cleanup
after := runtime.NumGoroutine()
if after > before {
t.Errorf("goroutine leak: before=%d after=%d", before, after)
}
}