我正在使用Context
和WithValue
向处理此*http.request
的后续函数传递一个uuid。此uuid已在授权标头中传递给REST调用以标识某个人。授权令牌已经过验证,需要访问以检查呼叫本身是否已获得授权。
我用过:
ctx := context.WithValue(r.Context(), string("principal_id"), *id)
但是高尔特抱怨道:
should not use basic type string as key in context.WithValue
可以用来检索此键的最佳选项是什么,而不是像简单字符串那样的基本类型?
答案 0 :(得分:35)
只需使用密钥类型:
type key int
const (
keyPrincipalID key = iota
// ...
)
由于您已定义了单独的类型,因此它永远不会发生冲突。即使你有两个包,pkg1.key(0) != pkg2.key(0)
。
答案 1 :(得分:1)
分享以上问题的简短答案。
GitHub Link
简而言之,context.WithValue()
需要interface{}
类型作为键和值。
我希望这会有所帮助。 谢谢。
答案 2 :(得分:0)
我通过执行以下操作达到了上述目的,并且感觉很干净
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())
答案 3 :(得分:0)
最好使用 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 的用户应该定义他们自己的键类型。为避免在分配给接口时进行分配{},上下文键通常具有具体的类型 struct{}。或者,导出的上下文键变量的静态类型应该是指针或接口。