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

WithValue и правила

Разбор инцидента упёрся в логи: по ним нельзя было связать запрос с файлом, который он грузил. Миша положил в контекст сквозной trace id, и все логи загрузки собрались в одну нить.

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

WithValue кладёт в контекст значение по ключу, но это не «мешок параметров»: ключи делают неэкспортируемыми типами, а контекст передают первым аргументом и не хранят в структурах.

WithValue

type ctxKey struct{} // неэкспортируемый тип-ключ

ctx := context.WithValue(parent, ctxKey{}, "значение")

v, ok := ctx.Value(ctxKey{}).(string)

WithValue возвращает новый контекст с парой ключ-значение. Ключ — пустая структура своего типа: неэкспортируемый тип не могут подделать другие пакеты, а значит, не будет коллизий ключей между библиотеками.

Почему ключ — не строка

ctx := context.WithValue(parent, "user_id", 42) // плохо

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

Правила использования

  • Первый аргумент. Контекст передают первым параметром функции — это закреплено соглашением Go-сообщества.
  • Не в структуре. Контекст не хранят в полях структур: он про конкретный вызов, а не про состояние объекта. Хранить в структуре — значит намекать, что контекст «переживает» вызов, а это почти всегда ошибка.
  • Только данные запроса. В контекст кладут то, что относится к вызову: идентификатор запроса, пользователя, трейсинг. Не параметры функции и не «настройки по умолчанию» — для них есть обычные аргументы.
В следующем уроке

Вы узнаете:

  • как иерархия значений работает у потомков
  • как helper-функция с типизированным возвратом достаёт значение
Задание · вопросы

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

Вопрос 1 из 3

Чем плох строковый ключ в context.WithValue(ctx, "user", v)?

Вопрос 2 из 3

Что уместно класть в контекст?

Вопрос 3 из 3

Почему поле ctx в структуре — анти-паттерн?

Итоги

WithValue — значения по неэкспортируемому ключу; контекст первым аргументом, не в структурах; внутри — только данные вызова. Контекст — это про отмену и метаданные запроса, а не про передачу параметров.

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