Ответ
Для корректной обработки отмены контекста в горутине используется блокирующий select с проверкой канала ctx.Done(). Этот механизм позволяет горутине вовремя прекратить свою работу, освободить ресурсы и избежать утечек.
Основной паттерн:
Канал ctx.Done() закрывается, когда контекст отменяется (из-за вызова cancel(), истечения таймаута или дедлайна). Чтение из закрытого канала происходит немедленно.
func worker(ctx context.Context, dataChan <-chan string) error {
for {
select {
case <-ctx.Done():
// Контекст был отменен. Прекращаем работу.
fmt.Println("Worker: context cancelled.")
// Важно вернуть ошибку, чтобы вызывающий код знал причину остановки.
return ctx.Err()
case data, ok := <-dataChan:
if !ok {
// Канал с данными закрыт, работа завершена.
return nil
}
// Выполняем полезную работу с данными
fmt.Printf("Processing data: %sn", data)
time.Sleep(500 * time.Millisecond) // Имитация работы
}
}
}Ключевые моменты и рекомендации:
Используйте
selectв циклах: В любой долгоживущей горутине, выполняющей работу в цикле,selectявляется обязательным для проверки отмены.Возвращайте
ctx.Err(): После получения сигнала изctx.Done(), проверьтеctx.Err(). Эта функция вернет причину отмены:context.Canceledилиcontext.DeadlineExceeded.Пробрасывайте контекст: Передавайте
context.Contextвниз по стеку вызовов всем функциям, которые могут быть долго выполняющимися или блокирующими (например, HTTP-запросы, запросы к БД).Освобождайте ресурсы: Перед выходом из функции по сигналу отмены убедитесь, что все захваченные ресурсы (файлы, соединения) корректно освобождены, например, с помощью
defer.