errgroup: первая ошибка
Групповая фаза загрузки выгружала пачку кусков в хранилище, и одной неудачи хватало, чтобы остановить всё. Аня на ревью показала errgroup, и скоуп загрузки переехал на него: первая ошибка останавливала остальных.
errgroup — это WaitGroup плюс сбор ошибок: Wait возвращает первую ошибку, а WithContext отменяет остальных при первом сбое.
Базовая форма
g, ctx := errgroup.WithContext(ctx)
for _, f := range files {
f := f
g.Go(func() error {
return upload(ctx, f)
})
}
if err := g.Wait(); err != nil {
log.Printf("первая ошибка: %v", err)
}
g.Go запускает функцию в горутине и запоминает ошибку, если функция её вернула. g.Wait ждёт всех и возвращает первую ошибку. По сравнению с WaitGroup из: не нужно руками собирать ошибки в канал или мьютекс.
Отмена при первом сбое
WithContext связывает группу с контекстом: первая ошибка отменяет контекст, и остальные горутины, слушающие ctx, сворачиваются. Это паттерн «запустить N запросов, сдаться при первой неудаче»: упал один — отменяем всех, кто ещё работает, чтобы не тратить ресурсы. И ещё: производный контекст отменяется при первой ненулевой ошибке или при первом возврате из Wait — что раньше. После g.Wait контекст отменён при любом исходе, даже успешном: читать у него Err или Value можно, а запускать на нём новую работу нельзя — она сразу получит отмену.
Чего errgroup не умеет
Wait возвращает только первую ошибку — остальные теряются. Если нужны все ошибки, их собирают сами (канал ошибок или errors.Join). И errgroup не лимитирует параллелизм сам по себе — для этого есть SetLimit, следующий урок.
Вы узнаете:
- почему «первая ошибка» — разумный выбор
- когда errgroup, а когда WaitGroup с каналом ошибок
Проверьте себя
Что такое errgroup по сути?
Что делает errgroup.WithContext?
Сколько ошибок возвращает g.Wait()?
правильных ответов
errgroup: запустить N функций, дождаться всех, получить первую ошибку. WithContext — отмена остальных при первом сбое; после Wait контекст отменён при любом исходе. Ошибки после первой — теряются.
10 000 ₽ · 60 минут · онлайн