如何使用Go获取当前命名空间和App Engine延迟功能?

时间:2016-10-08 16:59:09

标签: google-app-engine go

如果我设置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"
})

它有效,但感觉像是黑客。

1 个答案:

答案 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调用,该调用可以从中提取它上下文。