亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

傳入請求的上下文

傳入請求的上下文

Go
慕娘9325324 2021-09-13 16:29:26
我有時會遇到“上下文”概念,它通常是為所有傳入請求創建的。最近我閱讀了描述使用該包的Go 博客文章golang.org/x/net/context。然而,在玩過代碼并試圖重現文章的邏輯之后,我仍然很難理解如何將它用于每個傳入的請求,甚至為什么它對此有用。我應該如何組織我的代碼來為每個使用golang.org/x/net/context包的傳入請求創建上下文(以及它通常應該包含什么)?任何人都可以舉一個小例子并解釋什么如此有用以及為什么如此頻繁使用?
查看完整描述

2 回答

?
慕標5832272

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 頻道并中止它的工作并不總是很漂亮,但正如博客所示,它也不是非常痛苦。


查看完整回答
反對 回復 2021-09-13
?
largeQ

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 :)


查看完整回答
反對 回復 2021-09-13
  • 2 回答
  • 0 關注
  • 179 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號