2016-10-08 44 views
1

如果我把我的context.Context的命名空間,並調用一個延時功能:如何使用Go獲取當前命名空間和App Engine延遲功能?

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

不幸的是,你運氣不好。 Appengine不提供(導出)API調用來訪問與上下文關聯的名稱空間。

與上下文的名稱空間關聯由appengine/internal包處理,但「程序不應直接使用此包」。具有名稱空間的上下文由internal.NamespacedContext()調用獲得,上下文中的名稱空間「提取」在internal.NamespaceFromContext()中實現。這些不是公共API的一部分,所以你不能(不應該)使用它們。

你基本上有2個選項。一種是你提出的「哈克」方式,這種方式有效,你可以繼續使用它。

另一個是手動處理它,例如,通過手動將命名空間爲背景用自己的密鑰,如:

var namespaceKey = "myNsKey" 


ctx = context.WithValue(ctx, namespaceKey, "mynamespace") 

而當你需要它,你可以把它想:

ns := ctx.Value(namespaceKey) 

沒錯,這具有以負擔手動更新它,如果你忘記了,你會得到一個「無效的」或空的命名空間。因此,我個人認爲我現在會採用你的「黑客」方式(直到這個功能被添加到公共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調用即可。