Ответ
Метод Done()
интерфейса context.Context
возвращает канал (<-chan struct{}
). Этот канал закрывается, когда работа, связанная с данным контекстом, должна быть прервана.
Основное назначение — сигнализировать горутинам о необходимости graceful shutdown (корректного завершения).
Как это используется?
Чаще всего ctx.Done()
используется внутри оператора select
для неблокирующего ожидания сигнала отмены. Как только канал ctx.Done()
закрывается, чтение из него происходит немедленно, что позволяет выйти из цикла или завершить функцию.
Причины закрытия канала ctx.Done()
:
- Был вызван
cancel()
для контекста, созданного черезcontext.WithCancel()
. - Истек тайм-аут для контекста, созданного через
context.WithTimeout()
. - Наступил дедлайн для контекста, созданного через
context.WithDeadline()
.
Пример:
// ctx создается с таймаутом в 1 секунду
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() // Хорошая практика - вызывать cancel, даже если контекст истекает по таймауту
go func(ctx context.Context) {
select {
case <-time.After(2 * time.Second): // Эта операция займет больше времени, чем таймаут контекста
fmt.Println("Работа завершена")
case <-ctx.Done(): // Этот кейс сработает первым
fmt.Println("Работа прервана, так как контекст отменен:", ctx.Err())
}
}(ctx)
// Даем горутине время на выполнение, чтобы увидеть результат
time.Sleep(2 * time.Second)