Ответ
Используйте context.Context для корректной остановки горутин. Создайте контекст с отменой (context.WithCancel) и передайте его в горутины. При необходимости остановки вызовите cancel(). Горутины должны проверять ctx.Done() в цикле.
Пример:
ctx, cancel := context.WithCancel(context.Background())
go func() {
for {
select {
case <-ctx.Done():
return // завершаем горутину
default:
// работа горутины
}
}
}()
// Для остановки всех горутин
cancel()
Альтернативно можно использовать канал для сигнала остановки, но context предпочтительнее, так как он стандартизирован и поддерживает иерархию.