RunPool bounded worker pool with indexed results
Go
package pool
import (
"context"
"sync"
)
// RunPool applies fn to indices [0,n) using a fixed number of goroutines.
// Results and errors are stored at their index, so input order is preserved.
func RunPool[T any](ctx context.Context, n, workers int, fn func(context.Context, int) (T, error)) ([]T, []error) {
if workers < 1 {
workers = 1
}
out, errs := make([]T, n), make([]error, n)
idx := make(chan int, n)
var wg sync.WaitGroup
for w := 0; w < workers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := range idx {
out[i], errs[i] = fn(ctx, i)
}
}()
}
for i := 0; i < n; i++ {
if err := ctx.Err(); err != nil {
errs[i] = err
continue
}
idx <- i
}
close(idx)
wg.Wait()
return out, errs
}