Допустим, сервер получает сразу 100 запросов, по одной задаче в каждом. Выделим четыре обработчика и канал на восемь задач. Предположим, что за время поступления запросов ни одна задача не завершится. Четыре задачи могут выполняться, ещё восемь могут стоять в очереди. Если каждый запрос уже запустил горутину для отправки своей задачи, остальные 88 горутин могут ждать отправки. У очереди есть предел. Числу ожидающих нужен отдельный предел.
Буферизированный канал ограничивает число значений внутри него. Он не определяет, сколько горутин дойдут до блокирующей отправки. Перенос отправки в новую горутину лишь переносит ожидание. Небуферизированный канал синхронизирует отправителя и получателя при обмене значением, но тоже не ограничивает число прибывающих отправителей.
В этой схеме ответственность за допуск я бы возложил на точку приёма запросов. Она должна получить место до запуска дополнительной работы либо вернуть результат, обозначающий насыщение, если мест нет. Если вместо этого допуск приходится ждать, числу ожидающих тоже нужен предел, а ожиданию нужен срок. Иначе очередь просто переехала на шаг раньше.
За отправку сигнала отмены при уходе вызывающей стороны я бы назначил ответственным обработчик запроса. За проверку сигнала перед началом задачи из очереди и в подходящих точках остановки отвечают рабочие обработчики. Сам сигнал отмены ещё не говорит, когда освободится место. Ответственному за допуск нужно правило, по которому задача учитывается до тех пор, пока действительно не перестанет занимать ограничиваемый ресурс.
Если пакет заранее ограничен двенадцатью небольшими задачами, вполне разумно сразу запустить двенадцать горутин. Пул обработчиков тогда добавляет координацию, не обязательно улучшая ограничение. Какой компонент отвечает за предел, когда запросы продолжают поступать?