69

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

我用了:

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

但是 golint 抱怨说:

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

可以用来检索这个不是基本类型(如简单字符串)的键的最佳选项是什么?

4

4 回答 4

91

只需使用一个键类型:

type key int

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

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

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

于 2016-11-30T14:53:37.913 回答
5

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

提供的键必须是可比较的,并且不应该是字符串类型或任何其他内置类型,以避免使用上下文的包之间发生冲突。WithValue 的用户应该为键定义自己的类型。为避免在分配给 interface{} 时进行分配,上下文键通常具有具体类型 struct{}。或者,导出的上下文键变量的静态类型应该是指针或接口。

于 2021-06-23T12:55:55.187 回答
2

我通过执行以下操作来实现上述目标,并且觉得它很干净

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())
于 2020-06-17T06:18:19.863 回答
-10

为上述问题分享一个简短的答案。 GitHub Link 简而言之,context.WithValue()需要interface{}type 作为keysvalues

我希望这有帮助。谢谢你。

于 2019-02-27T20:12:16.923 回答