


context.Context передаёт сигнал отмены, срок выполнения и данные уровня запроса через цепочку вызовов. Отмена контекста не завершает горутину принудительно. Код должен наблюдать сигнал через Done() или передать контекст операции, которая умеет его обрабатывать.
В упражнении Mentoring.digital функция ожидает окончания таймера, но прекращает ожидание раньше, если истёк срок запроса. Это позволяет увидеть механизм без сети и внешних сервисов.
package main
import (
"context"
"fmt"
"time"
)
func wait(ctx context.Context, delay time.Duration) error {
timer := time.NewTimer(delay)
defer timer.Stop()
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}
func main() {
ctx, cancel := context.WithTimeout(
context.Background(), 20*time.Millisecond,
)
defer cancel()
fmt.Println(wait(ctx, time.Second))
}
При обычном выполнении срок контекста истекает раньше секундного ожидания, и функция возвращает context deadline exceeded. Для устойчивого автоматического теста лучше отдельно проверить уже отменённый контекст и заведомо успешное ожидание, не привязываясь к точному времени планировщика.
Возвращённую функцию cancel нужно вызвать даже тогда, когда операция может закончиться до срока. Она освобождает связанные с дочерним контекстом ресурсы. Типичная форма: создать контекст и сразу поставить defer cancel() в том же ограниченном по времени вызове.
В длинном цикле defer выполняется только при выходе из содержащей его функции. Поэтому не накапливайте тысячи отложенных отмен до конца большого обработчика. Выделите одну итерацию в отдельную функцию или завершайте её контекст явно после использования.
Обычно ctx является первым параметром функции. Дочерние операции получают контекст родителя, чтобы отмена запроса распространялась вниз. Создание нового Background внутри каждого слоя разрывает эту связь.
Не передавайте nil вместо контекста. Background подходит для корневой операции; TODO обозначает место, где подходящий контекст ещё предстоит определить. Через WithValue передают данные уровня запроса, а не обязательные аргументы бизнес-функции и не произвольные настройки.
Если вычисление не проверяет Done и вызываемая библиотека не принимает контекст, вызов cancel не остановит эту работу. Контекст также не откатывает уже выполненную запись во внешнюю систему. Отмена означает прекращение ожидания или работы согласно договору конкретной операции.
Для отправки результата в канал учитывайте оба исхода: получатель готов принять значение либо контекст отменён. Иначе горутина может остаться на блокирующей отправке, даже если основная функция уже ушла.
Практику конкурентного кода дают курсы Go. Диагностику зависающей горутины и контракт отмены можно разобрать с ментором по Go.