Ответ
Горутина определяет, что контекст отменён или истёк, используя механизм context.Context
.
Основной способ проверки — это использование метода ctx.Done()
, который возвращает канал. Когда контекст отменяется (например, вызовом cancel()
для context.WithCancel
или истечением времени для context.WithTimeout
/context.WithDeadline
), этот канал Done()
закрывается. Закрытие канала является сигналом для всех горутин, ожидающих на нём.
Горутина может отслеживать этот сигнал с помощью оператора select
:
func doWork(ctx context.Context) error {
select {
case <-ctx.Done():
// Контекст отменён или истёк. Возвращаем ошибку контекста.
fmt.Println("Работа отменена:", ctx.Err())
return ctx.Err()
default:
// Продолжаем выполнять полезную работу, если контекст активен.
fmt.Println("Работа продолжается...")
// Например, можно выполнить какую-то операцию, которая также принимает контекст
// time.Sleep(100 * time.Millisecond)
}
return nil
}
// Пример использования:
// ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// defer cancel()
// doWork(ctx)
Дополнительные способы проверки:
ctx.Err()
: Этот метод возвращает ошибку, если контекст был отменён (context.Canceled
) или истёк (context.DeadlineExceeded
). Если контекст ещё активен, он возвращаетnil
. Обычноctx.Err()
проверяют после того, какctx.Done()
канал закрылся, чтобы узнать причину отмены.
Важные аспекты:
- Иерархия контекстов: При отмене родительского контекста все его дочерние контексты (созданные с помощью
context.WithCancel
,context.WithTimeout
,context.WithDeadline
на основе родительского) также автоматически отменяются. - Пропагация отмены: Механизм
context.Context
позволяет легко распространять сигналы отмены по цепочке вызовов функций и горутин, обеспечивая корректное завершение операций и освобождение ресурсов.