// Created on savesnippets.com ยท https://savesnippets.com/pncAcaGkrDl6tq package main import ( "fmt" "sync" ) // Fan-out: each of N workers reads from `in` and writes to its own out channel. func fanOut(in <-chan int, n int, work func(int) int) []<-chan int { outs := make([]<-chan int, n) for i := 0; i < n; i++ { ch := make(chan int) go func() { defer close(ch) for v := range in { ch <- work(v) } }() outs[i] = ch } return outs } // Fan-in: merge any number of channels into one. func fanIn[T any](chs ...<-chan T) <-chan T { out := make(chan T) var wg sync.WaitGroup wg.Add(len(chs)) for _, c := range chs { c := c go func() { defer wg.Done() for v := range c { out <- v } }() } go func() { wg.Wait(); close(out) }() return out } func main() { in := make(chan int) go func() { defer close(in) for i := 0; i < 20; i++ { in <- i } }() workers := fanOut(in, 4, func(n int) int { return n * n }) for v := range fanIn(workers...) { fmt.Println(v) } }