Ответ
context.WithValue
используется для передачи данных, связанных с конкретным запросом (request-scoped data), вниз по стеку вызовов без необходимости явно передавать их в качестве аргументов каждой функции. Это особенно полезно для сквозной передачи метаданных, таких как ID запроса, токен аутентификации или информация для трассировки.
context.WithValue
возвращает копию родительского контекста с привязанной к нему новой парой ключ-значение.
Пример использования:
package main
import (
"context"
"fmt"
)
// Рекомендуется использовать пользовательский тип для ключа,
// чтобы избежать коллизий с ключами из других пакетов.
type contextKey string
const userKey = contextKey("user")
func processRequest(ctx context.Context) {
// Извлекаем значение из контекста
if user, ok := ctx.Value(userKey).(string); ok {
fmt.Println("Processing request for user:", user)
} else {
fmt.Println("Processing request for anonymous user")
}
}
func main() {
// Создаем базовый контекст
ctx := context.Background()
// Создаем новый контекст со значением
userCtx := context.WithValue(ctx, userKey, "admin")
processRequest(userCtx) // Output: Processing request for user: admin
processRequest(ctx) // Output: Processing request for anonymous user
}
Ключевые особенности и лучшие практики:
- Используйте неэкспортируемые пользовательские типы для ключей. Это предотвращает случайные коллизии имен ключей между разными пакетами. Использование простого типа
string
в качестве ключа является анти-паттерном. - Не используйте контекст для передачи обязательных параметров. Если функция требует для работы какой-то параметр, его следует передавать явно через аргументы. Это делает API вашей функции понятным и самодокументируемым.
context.WithValue
предназначен для опциональных, сквозных данных. - Значения должны быть потокобезопасными. Контекст может передаваться между несколькими горутинами, поэтому любое значение, помещенное в него, должно быть безопасно для одновременного доступа.
- Контекст неизменяем (immutable).
context.WithValue
не изменяет существующий контекст, а возвращает новый, который является его потомком.