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-функция с типизированным возвратом достаёт значение
Проверьте себя
Чем плох строковый ключ в context.WithValue(ctx, "user", v)?
Что уместно класть в контекст?
Почему поле ctx в структуре — анти-паттерн?
правильных ответов
WithValue — значения по неэкспортируемому ключу; контекст первым аргументом, не в структурах; внутри — только данные вызова. Контекст — это про отмену и метаданные запроса, а не про передачу параметров.
10 000 ₽ · 60 минут · онлайн