context.WithValue?Рекомендуемый подход - использовать неэкспортируемый тип в качестве ключа. Это гарантирует, что ключи разных пакетов никогда не пересекутся.
// внутри пакета auth
type ctxKey struct{}
var userKey = ctxKey{}
func WithUser(ctx context.Context, user *User) context.Context {
return context.WithValue(ctx, userKey, user)
}
func GetUser(ctx context.Context) *User {
u, _ := ctx.Value(userKey).(*User)
return u
}
// Опасно: строковые ключи могут совпасть
ctx = context.WithValue(ctx, "user", user1) // пакет auth
ctx = context.WithValue(ctx, "user", user2) // пакет billing
// user1 потерян!
Два разных пакета могут случайно использовать одинаковую строку "user" как ключ. С приватным типом это невозможно - тип ctxKey виден только внутри своего пакета.
type ctxKey int
const (
userKey ctxKey = iota
tokenKey
requestIDKey
)
Можно использовать iota для создания нескольких ключей одного приватного типа. Каждый ключ уникален в пределах пакета, а тип не экспортируется - коллизии с другими пакетами исключены.