Ответ
errgroup
— это пакет (golang.org/x/sync/errgroup
), который предоставляет средства для синхронизации группы горутин и централизованной обработки ошибок между ними.
Он решает распространенную задачу: запустить несколько параллельных операций, дождаться их завершения и, если хотя бы одна из них вернет ошибку, немедленно отменить остальные и вернуть первую возникшую ошибку.
Ключевые возможности:
- Синхронизация: Метод
g.Wait()
блокирует выполнение, пока все запущенные черезg.Go()
горутины не завершатся (аналогичноsync.WaitGroup
). - Распространение ошибки:
g.Wait()
возвращает первую не-nil
ошибку от любой из горутин. - Отмена через контекст: При использовании
errgroup.WithContext()
, если одна горутина возвращает ошибку, контекст, переданный в другие горутины, автоматически отменяется. Это позволяет им грациозно завершить свою работу, не выполняя лишних действий.
Пример: параллельное выполнение HTTP-запросов
func fetchURLs(ctx context.Context, urls []string) error {
g, gCtx := errgroup.WithContext(ctx)
for _, url := range urls {
// Захватываем переменную url в замыкании
url := url
g.Go(func() error {
req, err := http.NewRequestWithContext(gCtx, http.MethodGet, url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
// Если gCtx был отменен (из-за ошибки в другой горутине),
// http.Client вернет ошибку, и эта горутина завершится.
if err != nil {
return err
}
resp.Body.Close()
fmt.Printf("Fetched %s with status %sn", url, resp.Status)
return nil
})
}
// Ждем завершения всех горутин и возвращаем первую ошибку, если она была.
return g.Wait()
}
errgroup
является более мощной и удобной альтернативой sync.WaitGroup
, когда требуется не просто дождаться завершения горутин, но и управлять их отменой и обрабатывать ошибки.