Какая основная идея воркерпула?
Что проверяют
Понимаете ли вы, что воркерпул в Go нужен не потому, что горутины дорогие, а чтобы ограничить параллелизм и нагрузку на внешний ресурс. Следом обычно просят набросать реализацию и спрашивают, как её корректно остановить и сколько воркеров запускать.
Как отвечать
Идея: фиксированное число горутин читает задачи из общего канала, вместо новой горутины на каждую задачу. Горутина стартует со стеком в пару килобайт, десятки тысяч таких runtime переживёт спокойно. Не переживут база с лимитом соединений, чужой API с rate limit, память под одновременно обрабатываемые файлы. Пул превращает «сколько пришло задач» в «сколько работает одновременно».
Каркас реализации:
- канал задач:
jobs := make(chan Job), воркеры читают его черезfor job := range jobs. Закрывает канал только отправитель, когда задачи кончились; - ожидание:
sync.WaitGroup, причёмwg.Addвызывается до запуска горутины, а не внутри неё. В свежих версиях Go естьwg.Go(f), который делает оба шага сразу; - результаты: отдельный канал, который закрывает отдельная горутина после
wg.Wait(). Так читатель узнаёт о конце, а воркеры не упираются в запись; - отмена:
context.Contextиselectсctx.Done(), чтобы воркеры не висели после ошибки или таймаута; - обратное давление: небуферизованный или маленький буферизованный канал задач тормозит производителя, когда воркеры не успевают.
Число воркеров: для CPU-задач примерно runtime.GOMAXPROCS(0), для I/O его определяет лимит внешней стороны. Хорошо показать и готовые варианты: errgroup.Group с SetLimit(n) из golang.org/x/sync или семафор на буферизованном канале make(chan struct{}, n).
Где спотыкаются
Объясняют пул экономией на создании горутин, как в Java с потоками ОС. В Go это слабый аргумент, и интервьюер это знает.
Закрывают канал результатов сразу после запуска воркеров или из самого воркера. В первом случае получите панику при записи в закрытый канал, во втором панику от повторного закрытия.
Не думают об остановке: основной код перестал читать результаты из-за ошибки, воркеры заблокировались на отправке и остались висеть. Это утечка горутин, и лечится она контекстом.