Ответ
Используйте context.WithValue
только для передачи данных, связанных с запросом или транзакцией, таких как ID запроса, аутентификационные токены или метаданные. Не передавайте через контекст обязательные параметры функций или зависимости (например, базы данных, логгеры) — это усложняет API, делает код менее явным и затрудняет тестирование.
Ключи контекста должны быть неэкспортируемыми (например, type ctxKey string
или type contextKey int
), чтобы избежать коллизий между пакетами. Рекомендуется использовать пустые структуры (struct{}
) или неэкспортируемые типы для ключей, чтобы гарантировать уникальность. Значения, передаваемые через контекст, должны быть неизменяемыми и потокобезопасными.
Пример:
type ctxKey string
const requestIDKey ctxKey = "requestID"
func WithRequestID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, requestIDKey, id)
}
func GetRequestID(ctx context.Context) (string, bool) {
if v := ctx.Value(requestIDKey); v != nil {
if s, ok := v.(string); ok {
return s, true
}
}
return "", false
}
Важно: Всегда проверяйте тип извлеченного значения из контекста с помощью type assertion с ok
(как в GetRequestID
), чтобы избежать паники, если значение отсутствует или имеет неожиданный тип.