Почему канал для передачи задач должен быть длиной равной количеству элементов?
Что проверяют
Понимаете ли вы, чем буферизованный канал отличается от небуферизованного, и не повторяете ли заученное правило. Утверждение из вопроса верно не всегда, и интервьюер обычно ждёт, что вы это заметите и назовёте случай, где буфер действительно обязан вмещать все элементы.
Как отвечать
Начните с того, что буфер не меняет смысл передачи, он меняет только момент блокировки. Небуферизованный канал это точка встречи: отправитель ждёт получателя. Буфер на N позиций позволяет сделать N отправок, пока никто не читает.
Отсюда единственный случай, где длина обязана равняться количеству элементов: отправки происходят раньше, чем кто-то начнёт читать, либо читатель может уйти, не забрав всё.
results := make(chan Result, len(tasks)) // буфер на все задачи
for _, t := range tasks {
go func(t Task) { results <- process(t) }(t)
}
wg.Wait() // с меньшим буфером это дедлок
close(results)Горутины отправляют результат и завершаются, wg.Wait() дожидается их и только потом начинается чтение. Если буфера не хватит, часть горутин навсегда застрянет на отправке, а wg.Wait() не вернётся.
А вот в пуле воркеров, где получатели читают параллельно с отправкой, канал задач спокойно живёт небуферизованным: блокировка отправителя это и есть обратное давление, оно ограничивает очередь и память.
Где спотыкаются
Считают, что буфер ускоряет программу. Пропускную способность задаёт потребитель, буфер лишь сглаживает всплески. Под постоянной нагрузкой он всё равно заполнен и ведёт себя как небуферизованный, зато память под весь буфер выделяется сразу при make.
Второе: забывают про утечку горутин. Если читатель вышел по отмене контекста, а отправители продолжают писать в полный канал, они висят вечно, и заметно это только по pprof. Канал ошибок поэтому делают буферизованным хотя бы на одну позицию.
Третье: путают len и cap и строят на них логику. cap это размер буфера, len это текущее число элементов, и решение, принятое по len, устаревает сразу после проверки. Конец данных обозначает закрытие канала отправителем, а не опустевший буфер.