Зачем нужен context в Go
Вопрос
Расскажите, зачем нужен пакет context, как вы им пользуетесь в сервисе и какие ошибки встречали.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Отмена, дедлайн и значения запроса через цепочку вызовов
Дерево контекстов, отмена сверху вниз, дедлайн не позже родителя
WithCancel, WithTimeout, WithDeadline, WithValue; Cause, WithoutCancel, AfterFunc
Кооперативность: код должен слушать Done или передавать ctx в библиотеки
defer cancel, ключи своего типа, не класть зависимости
Практика: таймауты на внешние вызовы, отмена при уходе клиента, graceful shutdown
Что могут спросить следом
- Как передать trace id в фоновую задачу, которая переживёт запрос?
- Что будет, если не передавать ctx в запрос к базе?
Разбор
Context передаёт по цепочке вызовов сигнал отмены, дедлайн и значения конкретного запроса. На входе сервиса, в HTTP или gRPC-обработчике, я получаю контекст запроса и передаю его первым аргументом во все функции, которые ходят наружу: база, кеш, другие сервисы. На каждый внешний вызов ставлю свой таймаут через WithTimeout с defer cancel(). Контексты образуют дерево: если клиент ушёл, отменится его запрос и все запросы к базе, которые он начал. Дедлайн потомка не может быть позже родительского. Context кооперативный: он лишь закрывает Done, поэтому в своих циклах проверяю ctx.Err(). В значения кладу только request id, пользователя, trace, а ключи делаю своим неэкспортируемым типом. Ошибки из практики: забытый cancel, фоновая работа на r.Context(), которая обрывалась после ответа (лечится WithoutCancel), и долгая функция, игнорирующая ctx, из-за которой graceful shutdown упирался в таймаут.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.