"Семафор".
Запустить 10,000 горутин в Go дешево. А вот открыть 10,000 коннектов к базе или внешнему API - дорого и больно.
Если вы просто запустите go func() в цикле по всему слайсу данных, OOM Killer или таймауты придут мгновенно. Нам нужно ограничить количество одновременно работающих воркеров.
Самый идиоматичный способ в Go - буферизированный канал в роли семафора.
Реализация:
func ProcessItems(items []int) {
maxConcurrency := 5
// Семафор — канал с емкостью = лимиту
sem := make(chan struct{}, maxConcurrency)
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
// Блокируемся здесь, если в канале уже 5 токенов
sem <- struct{}{}
go func(val int) {
defer wg.Done()
// Освобождаем слот в семафоре при выходе
defer func() { <-sem }()
// Тяжелая логика тут
process(val)
}(item)
}
wg.Wait()
}
Почему это круто:
1. Backpressure: Мы не создаем миллион горутин, которые висят в sleep. Горутина создается только когда есть свободный слот (точнее, цикл for блокируется на записи в канал).
2. Простота: Никаких внешних библиотек.
Нюанс для профи:
Если порядок обработки не важен - это идеальное решение. Если важен - смотрите в сторону Pipeline паттерна.
#golang #concurrency #semaphore #architecture
👉 @golang_lib