Ответ вслух Senior context обновлено

Как устроен context внутри

Вопрос

Как реализованы WithCancel и WithValue внутри пакета context? Почему поиск значения медленный и как отмена доходит до потомков?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Каждая обёртка это отдельный узел, ссылающийся на родителя. cancelCtx содержит мьютекс, канал done, который создаётся лениво при первом вызове Done, мапу дочерних отменяемых контекстов и ошибку с причиной. При WithCancel новый узел ищет ближайшего отменяемого предка из пакета context и регистрируется в его мапе детей.

Что должно прозвучать в ответе

  • cancelCtx: мьютекс, лениво создаваемый канал done, мапа детей, ошибка и причина

  • При создании потомок регистрируется у ближайшего отменяемого предка; если предок чужой реализации, запускается горутина-наблюдатель

  • cancel закрывает done, рекурсивно отменяет детей и удаляется из родителя

  • timerCtx добавляет таймер, который вызывает cancel

  • valueCtx хранит одну пару ключ-значение и ссылку на родителя, Value идёт вверх по цепочке: O(глубины)

Что могут спросить следом

  • Почему не стоит делать десятки WithValue подряд?
  • Что делает context.AfterFunc внутри?

Разбор

Каждая обёртка это отдельный узел, ссылающийся на родителя. cancelCtx содержит мьютекс, канал done, который создаётся лениво при первом вызове Done, мапу дочерних отменяемых контекстов и ошибку с причиной. При WithCancel новый узел ищет ближайшего отменяемого предка из пакета context и регистрируется в его мапе детей. Если родитель чужой реализации, запускается горутина, которая ждёт parent.Done() и отменяет потомка. Отмена закрывает done, рекурсивно отменяет всех детей и удаляет себя из родителя. timerCtx это cancelCtx плюс time.AfterFunc, который вызовет cancel по дедлайну. valueCtx хранит ровно одну пару ключ-значение, а Value идёт вверх по цепочке, сравнивая ключи, пока не найдёт или не дойдёт до корня. Поэтому длинная цепочка WithValue делает поиск линейным, и в контексте не стоит держать много значений: лучше одна структура с данными запроса.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.