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 с, потомку просят 10 с. Через сколько отменится потомок?
Останавливает ли cancel() горутину принудительно?
Безопасен ли повторный вызов cancel()?
правильных ответов
WithCancel/Timeout/Deadline создают отменяемые контексты; cancel — идемпотентен, вызывается через defer; дедлайн потомка ≤ дедлайна родителя.
10 000 ₽ · 60 минут · онлайн