Gaurd strategy
func main() {
maxGoroutines := 10
guard := make(chan struct{}, maxGoroutines)
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
guard <- struct{}{} // Blocks if channel is full (reaches cap)
go func(n int) {
defer wg.Done()
defer func() { <-guard }() // Release slot when done
doWork(n)
}(i)
}
wg.Wait()
}
Collect errors if needed in another buffered channel
func main() {
size := 100
maxGoroutines := 10
guard := make(chan struct{}, maxGoroutines)
theErrors := make(chan error, size)
var wg sync.WaitGroup
for i := 0; i < size; i++ {
wg.Add(1)
guard <- struct{}{} // Blocks if channel is full (reaches cap)
go func(n int) {
defer wg.Done()
defer func() { <-guard }() // Release slot when done
err := doWork(n)
if err != nil {
theErrors <- fmt.Errorf("error, when doing the work. Error: %v", err)
return
}
}(i)
}
wg.Wait()
select {
case e := <- theErrors:
log.Fatalf("error, encountered during work. Error: %v", e)
default:
}
}