如果我设置context.Context
的命名空间并调用延迟函数:
ctx := appengine.NewContext(r)
ctx, err := appengine.Namespace(ctx, "mynamespace")
delayFunc.Call(ctx)
我如何找到它的名字:
var delayFunc = delay.Func("my-func", func(ctx context.Context) {
// How do I extract "mynamespace" from ctx?
})
以下是可接受的做法吗?
var delayFunc = delay.Func("my-func", func(ctx context.Context) {
n := datastore.NewKey(ctx, "E", "e", 0, nil).Namespace()
// n == "mynamespace"
})
它有效,但感觉像是黑客。
答案 0 :(得分:1)
不幸的是,你运气不好。 Appengine不提供(导出的)API调用来访问与上下文关联的命名空间。
与上下文的名称空间关联由appengine/internal
包处理,但"程序不应直接使用此包" 。带有命名空间的上下文是通过internal.NamespacedContext()
调用和命名空间"提取"来获得的。来自上下文是在internal.NamespaceFromContext()
中实现的。这些不是公共API的一部分,因此您不能(不应该)使用它们。
你基本上有两个选择。一个是" hacky"你提出的方式,哪个有效,你可以继续使用它。
另一个是手动处理它,例如通过使用您自己的密钥手动将命名空间放入上下文中,例如:
var namespaceKey = "myNsKey"
ctx = context.WithValue(ctx, namespaceKey, "mynamespace")
当你需要它时,你可以得到它:
ns := ctx.Value(namespaceKey)
是的,这有必要手动更新它的负担,如果你忘了,你会得到一个"无效"或空命名空间。所以我个人会和你的" hacky"现在的方式(直到将此功能添加到公共API,如果有的话)。
如果你采用手动方式,摆脱"风险"因此,您可以创建一个辅助函数,它可以与appengine.Namespace()
调用一起处理这个问题,因此您不会忘记它并且它是安全的。它看起来像这样:
func SetNS(ctx context.Context, ns string) context.Context {
ctx = ctx, err := appengine.Namespace(ctx, ns)
if err != nil {
// handle error
}
ctx = context.WithValue(ctx, namespaceKey, ns)
return ctx
}
使用它:
ctx = SetNS(ctx, "mynamespace")
但是当你需要从上下文访问命名空间时,这可能是一种罕见的情况,就像你需要它一样,它可能就足以将上下文传递给正确的(Appengine)API调用,该调用可以从中提取它上下文。