修复 "should not use basic type string as key in context.WithValue" golint

Fix "should not use basic type string as key in context.WithValue" golint

我在使用 ContextWithValue 时将一个 uuid 传递给处理此 *http.request 的后续函数。此 uuid 已在授权 header 中传递给 REST 调用以识别人员。授权令牌已验证,需要可访问以检查调用本身是否已获得授权。

我用过:

ctx := context.WithValue(r.Context(), string("principal_id"), *id)

但是 golint 抱怨:

should not use basic type string as key in context.WithValue

可用于检索非基本类型(如简单字符串)的密钥的最佳选项是什么?

只需使用密钥类型:

type key int

const (
    keyPrincipalID key = iota
    // ...
)

既然你定义了一个单独的类型,它永远不会发生冲突。即使你有两个包,pkg1.key(0) != pkg2.key(0).

另请参阅:Go Blog about key collisions in context

分享对上述问题的简要回答。 GitHub Link 简而言之,context.WithValue() 需要 interface{} 输入 keysvalues.

希望对您有所帮助。 谢谢。

我是通过下面的方式实现的,感觉还挺干净的

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'

并且可以打印出key的值,

fmt.Println("Key is:", ContextKeyDeleteCaller.String())

使用类型 struct{} 好多了。

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

The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys. To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.