Здравствуйте.
Есть сервис, который обрабатывает некоторый поток данных пулом воркеров.
Вот упрощенный, в целях демонстрации, код:
spoilerpackage main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var (
maxWorkers = 5
pool = make(chan struct{}, maxWorkers)
input = make(chan int, 0)
results = make([]int, 0)
)
func main() {
go func() {
defer close(input)
// какой-то рандомный input
rand.Seed(time.Now().Unix())
limit := rand.Intn(40) + 1
for i := 0; i < limit; i++ {
input <- i
}
}()
var wg sync.WaitGroup
// главный процесс пула воркеров
for i := range input {
pool <- struct{}{}
wg.Add(1)
go func(i int) {
defer func() {
wg.Done()
<-pool
}()
// здесь race condition
results = append(results, pow(i+1, 2))
}(i)
}
wg.Wait()
fmt.Println(results)
}
func pow(n int, power int) int {
fmt.Println("worker started")
time.Sleep(time.Second * 2)
return n * power
}
Как в этом случае избежать race condition? Mutex здесь не поможет, так как он будет блокировать всех воркеров, и они будут выполняться по очереди.
Из вариантов: использовать дополнительный канал.
Но может есть более удобный способ?