Материал проходит вычитку — возможны неточности.
Урок 108 из 118

WithCancel, Timeout, Deadline

Миша повесил таймаут на шаг экспорта, а отмену всей загрузки привязал к вкладке клиента: после ухода пользователя конвейер сворачивался за секунды. Сергей на ревью напомнил про defer cancel и про дедлайн потомка, который не может быть позже родительского.

Главная мысль

контексты отмены создают тремя способами — WithCancel, WithTimeout, WithDeadline; cancel идемпотентен, его всегда вызывают через defer, а дедлайн потомка не может быть позже дедлайна родителя.

Три способа отмены

ctx, cancel := context.WithCancel(parent)
ctx, cancel := context.WithTimeout(parent, 3*time.Second)
ctx, cancel := context.WithDeadline(parent, time.Now().Add(3*time.Second))

Все три возвращают новый контекст и функцию cancel. WithCancel отменяется только вручную, WithTimeout и WithDeadline — автоматически по времени (это одно и то же под капотом: таймаут — это дедлайн «сейчас + N»).

Cancel — через defer

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

cancel всегда вызывают через defer: даже если функция закончится раньше срока, ресурсы таймера освободятся сразу. Идемпотентность — гарантия: повторный cancel безопасен, ничего не падает.

Иерархия дедлайнов

parent, _ := context.WithTimeout(context.Background(), 5*time.Second)
child, _ := context.WithTimeout(parent, 10*time.Second)
// ребёнок фактически живёт 5 секунд, не 10

Дедлайн потомка не может быть позже дедлайна родителя: родитель отменяется — отменяются все потомки, цепочкой. Поэтому «дать ребёнку больше времени, чем родителю» невозможно: время ограничивается сверху самым строгим предком.

В следующем уроке

Вы узнаете:

  • как context.AfterFunc запускает функцию по отмене
  • почему WithTimeout и WithDeadline — одна механика
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Родительский контекст живёт 1 с, потомку просят 10 с. Через сколько отменится потомок?

Вопрос 2 из 3

Останавливает ли cancel() горутину принудительно?

Вопрос 3 из 3

Безопасен ли повторный вызов cancel()?

Итоги

WithCancel/Timeout/Deadline создают отменяемые контексты; cancel — идемпотентен, вызывается через defer; дедлайн потомка ≤ дедлайна родителя.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки