Исправлено "не следует использовать строку базового типа в качестве ключа в 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{} введите как ключи и значения.

Надеюсь, это поможет. Спасибо.

Другие вопросы по тегам