Проверяет понимание внутреннего устройства канала ctx.Done() в Go и причин, по которым его нельзя закрыть вручную.
В Go контекст (context.Context) предоставляет канал Done(), который сигнализирует о завершении операции. Этот канал закрывается автоматически, когда контекст отменяется через вызов cancel() или по истечении срока (deadline). Закрытие канала — это способ уведомить все горутины, ожидающие на нем, что работа завершена.
Канал Done() создается внутри пакета context и управляется его внутренними механизмами. Если вы попытаетесь вызвать close(ctx.Done()), это приведет к панике, потому что канал уже может быть закрыт (например, после отмены контекста). Даже если контекст еще активен, закрытие канала вручную нарушит контракт: другие части программы могут ожидать, что канал закроется только при отмене, и это приведет к гонкам данных или некорректному поведению.
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // обязательно вызываем для освобождения ресурсов
go func() {
select {
case <-ctx.Done():
fmt.Println("Отмена получена")
case <-time.After(2 * time.Second):
fmt.Println("Таймаут")
}
}()
// Отменяем контекст через некоторое время
time.Sleep(1 * time.Second)
cancel() // закрывает ctx.Done() автоматическиЕсли вызвать close(ctx.Done()) до отмены, то при последующем вызове cancel() пакет context попытается закрыть уже закрытый канал, что вызовет panic. Это нарушит работу программы. Поэтому разработчики Go явно запрещают ручное закрытие, предоставляя только функцию cancel() для управления жизненным циклом.
Используйте механизм отмены через cancel() или WithTimeout/WithDeadline, чтобы корректно закрывать канал Done(). Это гарантирует безопасность и предсказуемость в конкурентных программах, избегая паник и гонок данных.