2 回答

TA貢獻1966條經驗 獲得超4個贊
上下文傳遞最常見的需求之一是將傳出請求與傳入請求相關聯。我已將其用于多種目的,例如:
我希望我的數據庫組件的錯誤日志包含來自它的 http 請求的完整 url。
傳入的 http 請求包含一組標頭,我需要保留這些標頭并將其傳遞給我下游調用的其他 http 服務(可能是出于跟蹤原因)。
我想檢查其他組件中傳入的 http 請求,以進行訪問控制或用戶身份驗證或其他任何操作。這可能在 http 處理程序層,或我的應用程序的其他部分。
許多語言和平臺都有方便/神奇的方式來獲取當前的 Http 請求。C# 具有HttpRequest.Current
全局可用(通過線程本地存儲)的任何想要了解當前 http 請求上下文的人。您可以在其上設置任意數據以傳達各種上下文數據。其他平臺也有類似的設施。
由于 go 沒有用于 goroutine 本地存儲的設施,因此無法在當前 http 請求的上下文中存儲全局變量。相反,在系統邊界(傳入請求)初始化上下文是慣用的,并將其作為參數傳遞給需要訪問該信息的任何下游組件。
一種非常簡單的方法是使用當前的 http 請求創建一個上下文對象并傳遞它:
func someHandler(w http.ResponseWriter, r * http.Request){ ctx := context.WithValue(context.Background(),"request",r) myDatabase.doSomething(ctx,....)}
您當然可以將其限制為您需要傳遞的更有針對性的數據集,而不是整個請求。
上下文包的另一件事(我認為該博客在指出方面做得很好)是超時或截止日期的通用框架。
請注意,上下文包不會為您強制超時。由接收上下文對象的組件來觀察 Done 通道并自行取消他們自己的 http 請求或數據庫調用或計算或其他任何東西。
編輯 - 超時
能夠從組件外部管理超時非常有用。如果我有一個數據庫模塊,我不需要硬編碼超時值,只需能夠處理從外部觸發的超時。
我這樣做的一種方法是在每個傳入請求進行多個數據庫/服務調用的服務中。如果總時間超過 1 秒,我想中止所有出站操作并返回部分或錯誤結果。在頂層使用超時初始化上下文并將其傳遞給所有依賴項是一種非常簡單的管理方法。
依賴項收聽 Done 頻道并中止它的工作并不總是很漂亮,但正如博客所示,它也不是非常痛苦。

TA貢獻2039條經驗 獲得超8個贊
我同意這里的@captncraig 回答。但我只是想輕松更新與傳遞上下文相關的代碼。
假設你有一條路線 /foo http.Handle("/foo", SimpleContextHandler(passContextHandler))
在這種情況下SimpleContextHandler就像一個構造函數,你可以像下面一樣啟動它。
type SimpleContextHandler func(w http.ResponseWriter, r *http.Request)
func (fn SimpleContextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(context.Background(), "Foo", "bar")
fn(w, r.WithContext(ctx))
}
func passContextHandler(w http.ResponseWriter, r *http.Request) {
bar := r.Context().Value("Foo").(string)
w.Write([]byte(bar))
}
玩得開心,如果您仍然覺得可以改進,請編輯我的答案,因為幾周前我也開始使用 GoLang :)
- 2 回答
- 0 關注
- 179 瀏覽
添加回答
舉報