Исправлено "не следует использовать строку базового типа в качестве ключа в context.WithValue" golint
Я передаю UUID в использовании Context
а также WithValue
для последующих функций, которые обрабатывают это *http.request
, Этот uuid был передан в заголовке авторизации вызову REST для идентификации человека. Токен авторизации проверен и должен быть доступен, чтобы проверить, авторизован ли сам вызов.
Я использовал:
ctx := context.WithValue(r.Context(), string("principal_id"), *id)
Но Голинт жалуется:
should not use basic type string as key in context.WithValue
Каков наилучший вариант, который можно использовать для извлечения этого ключа, который не является базовым типом, таким как простая строка?
4 ответа
Просто используйте тип ключа:
type key int
const (
keyPrincipalID key = iota
// ...
)
Поскольку вы определили отдельный тип, он никогда не будет конфликтовать. Даже если у вас есть две посылки, pkg1.key(0) != pkg2.key(0)
,
Смотрите также: Go Blog о ключевых столкновениях в контексте.
Тип использования
type ctxKey struct{} // or exported to use outside the package
ctx = context.WithValue(ctx, ctxKey{}, 123)
fmt.Println(ctx.Value(ctxKey{}).(int) == 123) // true
Ссылка: https://golang.org/pkg/context/#WithValue
Предоставленный ключ должен быть сопоставимым и не должен быть строкового типа или любого другого встроенного типа, чтобы избежать конфликтов между пакетами, использующими контекст. Пользователи WithValue должны определять свои собственные типы ключей. Чтобы избежать выделения при назначении интерфейсу {}, ключи контекста часто имеют конкретный тип struct {}. В качестве альтернативы статическим типом экспортируемых переменных ключа контекста должен быть указатель или интерфейс.
Я добиваюсь вышеизложенного, выполняя следующие действия и чувствую, что это довольно чисто
package util
import "context"
type contextKey string
func (c contextKey) String() string {
return string(c)
}
var (
// ContextKeyDeleteCaller var
ContextKeyDeleteCaller = contextKey("deleteCaller")
// ContextKeyJobID var
ContextKeyJobID contextKey
)
// GetCallerFromContext gets the caller value from the context.
func GetCallerFromContext(ctx context.Context) (string, bool) {
caller, ok := ctx.Value(ContextKeyDeleteCaller).(string)
return caller, ok
}
// GetJobIDFromContext gets the jobID value from the context.
func GetJobIDFromContext(ctx context.Context) (string, bool) {
jobID, ok := ctx.Value(ContextKeyJobID).(string)
return jobID, ok
}
..и затем установить контекст,
ctx := context.WithValue(context.Background(), util.ContextKeyDeleteCaller, "Kafka Listener")
..получить значение из контекста,
caller, ok := util.GetCallerFromContext(ctx)
if !ok {
dc.log.Warn("could not get caller from context")
}
fmt.Println("value is:", caller) // will be 'Kafka Listener'
и может распечатать значение ключа, выполнив,
fmt.Println("Key is:", ContextKeyDeleteCaller.String())
Делимся кратким ответом на поставленный выше вопрос. GitHub Ссылка Короче говоря, context.WithValue()
потребности interface{}
введите как ключи и значения.
Надеюсь, это поможет. Спасибо.