npx claudepluginhub jamesprial/prial-plugins --plugin golang-workflowThis skill uses the workspace's default tool permissions.
**Only the sender closes channels.** Receivers never close.
Provides code examples for Go goroutines, channels (unbuffered, buffered, directional, closing), select statements, and sync patterns when writing concurrent Go code.
Guides Go concurrency: goroutine lifetimes with WaitGroups, channels for communication, mutexes for shared state, preventing leaks and data races.
Implements Go concurrency patterns using goroutines, channels, sync primitives, and context for building concurrent apps, worker pools, pipelines, and debugging race conditions.
Share bugs, ideas, or general feedback.
Only the sender closes channels. Receivers never close.
func generator() <-chan int {
ch := make(chan int)
go func() {
defer close(ch) // Sender closes
for i := 0; i < 10; i++ {
ch <- i
}
}()
return ch
}
func main() {
for num := range generator() {
fmt.Println(num)
}
}
func main() {
ch := make(chan int)
go func() {
for i := 0; i < 10; i++ {
ch <- i // Panic: send on closed channel
}
}()
for i := 0; i < 5; i++ {
<-ch
}
close(ch) // WRONG: receiver closes
}
func fanOut(input <-chan int, workers int) []<-chan int {
outputs := make([]<-chan int, workers)
for i := 0; i < workers; i++ {
outputs[i] = worker(input)
}
return outputs
}
func worker(input <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for n := range input {
out <- n * 2
}
}()
return out
}
func fanIn(channels ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
wg.Add(len(channels))
for _, ch := range channels {
go func(c <-chan int) {
defer wg.Done()
for n := range c {
out <- n
}
}(ch)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
func orDone(ctx context.Context, ch <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for {
select {
case <-ctx.Done():
return
case v, ok := <-ch:
if !ok {
return
}
select {
case out <- v:
case <-ctx.Done():
return
}
}
}
}()
return out
}
<-chan (receive), chan<- (send)ok when not using range: v, ok := <-chselect)// Unbuffered: synchronous handoff
ch := make(chan int)
// Buffered: decouples sender/receiver
ch := make(chan int, 10)