Основные способы:
1. Context — идиоматичный способ:
ctx, cancel := context.WithCancel(context.Background())
for i := 0; i < 5; i++ {
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
// работа
}
}
}(ctx)
}
cancel() // завершает все горутины
2. Done-канал — закрытие канала как broadcast-сигнал:
done := make(chan struct{})
close(done) // все горутины, слушающие done, получат сигнал
Context предпочтительнее — он поддерживает дедлайны, таймауты и передачу значений. Для ожидания завершения — добавь sync.WaitGroup.