Материал проходит вычитку — возможны неточности.
Урок 118 из 118

SetLimit и границы errgroup

Без ограничений errgroup запускала всё сразу — на пачке из тысяч файлов снова вырастала тысяча горутин. Миша добавил SetLimit, и группа превратилась в аккуратный пул со встроенным лимитом.

Главная мысль

SetLimit превращает errgroup в лёгкий worker pool: не больше N функций одновременно, а блокируется при исчерпании лимита сама вызывающая горутина.

Лимит параллелизма

g, ctx := errgroup.WithContext(ctx)
g.SetLimit(8)

for _, f := range files {
    f := f
    g.Go(func() error {
        return upload(ctx, f)
    })
}

g.Wait()

С лимитом 8 одновременно работает не больше восьми функций. Остальные не «встают в очередь» — блокируется сама горутина, вызвавшая Go, до тех пор, пока не освободится слот. Внутри это обычный семафор на канале — та же техника, что в следующем уроке: Go отправляет токен, завершённая функция возвращает его.

Errgroup как пул

SetLimit превращает errgroup в лёгкий worker pool из: ограниченный параллелизм плюс готовый сбор ошибок и отмена по первому сбою. Для пачки однотипных задач это короче и безопаснее самописного пула с каналами и WaitGroup.

TryGo

Если блокироваться в Go не хочется, есть TryGo: при исчерпанном лимите он вернёт false, вместо того чтобы ждать. Удобно, когда лимит — это «сколько ещё можем принять», а не «сколько будем ждать».

В следующем уроке

Вы узнаете:

  • что делают SetLimit(-1) и SetLimit(0)
  • как TryGo реализует backpressure
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Что означает g.SetLimit(8)?

Вопрос 2 из 3

Что делают SetLimit(0) и SetLimit(-1)?

Вопрос 3 из 3

Меняет ли лимит результат errgroup?

Итоги

SetLimit(N) — семафор внутри errgroup: N одновременных функций, Go блокируется на полном лимите, TryGo — неблокирующая попытка. Лимит снимает отрицательное значение, а не ноль.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки