Проверяет понимание корректной остановки горутин и воркеров в Go при отмене контекста, а также использование select для обработки отмены.
В Go контекст (context.Context) — это стандартный механизм для передачи сигналов отмены и дедлайнов между горутинами. Когда вызывается cancel(), все горутины, которые получили этот контекст, могут узнать об этом через канал ctx.Done(). Для корректной остановки воркеров нужно, чтобы каждая горутина в цикле проверяла этот канал.
Рассмотрим пул воркеров, которые читают задачи из канала. Без учёта отмены они будут работать вечно. Добавим select, который одновременно слушает канал задач и ctx.Done():
func worker(ctx context.Context, tasks <-chan int) {
for {
select {
case task, ok := <-tasks:
if !ok {
return // канал закрыт
}
process(task)
case <-ctx.Done():
return // контекст отменён
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
tasks := make(chan int)
go worker(ctx, tasks)
// отправляем задачи...
cancel() // останавливаем воркер
}Здесь select блокируется до тех пор, пока не появится задача или не сработает отмена. При вызове cancel() воркер выходит из цикла и завершается.
Использование select с ctx.Done() — стандартный идиоматический способ остановки горутин в Go. Это позволяет писать надёжные и управляемые конкурентные программы, избегая утечек ресурсов. Применяйте этот паттерн везде, где есть длительные циклы или блокирующие операции.