Вопрос проверяет понимание паттернов конкурентности в Go, в частности graceful shutdown нескольких горутин при ошибке.
В Go горутины не имеют встроенного механизма уведомления друг друга об ошибках. Если одна горутина завершилась с ошибкой, остальные продолжают работу, что может привести к утечкам ресурсов или некорректному поведению. Для решения этой задачи применяются контексты с отменой и пакет errgroup.
Создайте контекст с функцией отмены и передавайте его во все горутины. При возникновении ошибки вызовите cancel(), а горутины должны проверять ctx.Done() в цикле или select.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
select {
case <-ctx.Done():
return
case result <-ch:
// обработка
}
}()
// при ошибке:
cancel()Errgroup из golang.org/x/sync/errgroup предоставляет удобную обёртку. Он автоматически отменяет контекст при первой ошибке и ожидает завершения всех горутин.
g, ctx := errgroup.WithContext(context.Background())
for i := 0; i < 3; i++ {
i := i
g.Go(func() error {
if i == 1 {
return errors.New("ошибка")
}
select {
case <-ctx.Done():
return ctx.Err()
default:
time.Sleep(time.Second)
}
return nil
})
}
if err := g.Wait(); err != nil {
log.Println("ошибка:", err)
}Используйте errgroup для группового управления горутинами с автоматической отменой при ошибке. Для более тонкого контроля применяйте context.WithCancel вручную. Это стандартный паттерн для надёжной обработки ошибок в конкурентном коде Go.