Всем привет,
Пишу небольшой CLI на Go, shotcheck, который проверяет каждый PNG в папке на точное соответствие размеру, который нужен слоту в App Store. Пул воркеров (по умолчанию 8) читает имена из jobs, проверяет файлы и отправляет Result в небуферизованный канал results. collect в main читает их, и на первом же плохом результате вызывает cancel() и возвращает ошибку. Видимое поведение правильное: печатается checked 11 of 40, потом FAIL с именем файла, код выхода 1.
Проблема у меня с флагом -debug. После ошибки я печатаю runtime.NumGoroutine() после короткого sleep и ожидаю 1. Получаю 10 при 8 воркерах и 6 с -workers 4, то есть всегда workers + 2. Более долгий sleep (2 с, потом 5 с) ничего не меняет. Пишу по памяти о последнем запуске, потому что сейчас не могу запустить Go на этой машине.
Горутина-продюсер останавливается и jobs закрывается, так что я не понимаю, почему отменённый контекст не остановил остальных. Пробовал переставлять cancel(), без изменений. Подозреваю WaitGroup или то, что defer cancel() срабатывает слишком поздно.
В CLI это безвредно, потому что процесс завершается. Но я хочу использовать этот пул в долгоживущем CI-хелпере, и там, по-моему, эти горутины будут копиться при каждом упавшем запуске и сильно тормозить машину.
Часть с воркерами:
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for path := range jobs {
r := checkShot(path)
results <- r
}
}()
}
go func() {
wg.Wait()
close(results)
}()
Может, я упускаю что-то простое? Спасибо, что прочитали))