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

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

我應該在每個傳入請求中創建新的上下文嗎?

我應該在每個傳入請求中創建新的上下文嗎?

Go
拉莫斯之舞 2023-08-14 14:39:41
在過去的幾天里,我一直在閱讀有關 Go 的內容,并且我不斷回顧的一個概念是上下文。我想我理解創建這樣一個結構背后的動機。我不明白的是在傳入 HTTP 請求中使用上下文時的特定用例。假設我們有一個追隨者httpHandlerFunc。在該處理程序內部,我們調用一個需要傳遞上下文的函數。我經??吹竭@個解決方案func myHandler(w http.ResponseWriter, r *http.Request) {  ctx := context.WithValue(context.Background(), "request", r)  otherFunc(ctx)}我的問題是,為什么我們不直接從請求中傳遞上下文,就像這樣func myHandler(w http.ResponseWriter, r *http.Request) {  otherFunc(r.Context())}既然我們希望上下文流過我們的程序,那么傳遞請求的上下文不是更有意義嗎?我認為創建后臺上下文是我們只想在根父級中執行的操作,就像init()函數一樣。
查看完整描述

2 回答

?
森林海

TA貢獻2011條經驗 獲得超2個贊

您可能會錯過上下文的要點 - 據說是由于您正在處理的 HOWTO 很差。

在上下文中攜帶任意值的可能性實際上是這種類型的一個缺陷,其設計者對此感到遺憾,因為它創建了一種反模式(處理上下文作為某種狀態的正確方法是明確地擁有一組值)傳遍了)。

上下文存在的主要原因是它們提供了信號的樹狀傳播(在上下文的情況下是取消或“完成”)。所以上下文背后的原始想法如下:

  1. “根”上下文對象是為傳入請求創建的。

  2. 需要代表請求執行的每個“任務”都與其自己的上下文相關聯,該上下文源自請求的上下文。

  3. 這些任務可能會產生其他任務等等。

    正如您所看到的,形成了“工作單元”的層次結構,鏈接到對象,這是這些單元存在和執行的原因。

  4. 當傳入請求被取消時(例如,客戶端的套接字斷開連接),與其關聯的上下文對象也會被取消,然后所有鏈接的任務都會收到它,因為它從生成的上下文樹的根向下傳播到其離開——確保請求執行的所有任務(最終)被取消。

    當然,為了使其發揮作用,每個“任務”(通常是一個執行某些操作的 goroutine)都需要從傳遞給它的上下文中“監聽”該“完成”信號。

上下文還支持開箱即用的超時,因此您可以創建一個上下文,該上下文在經過一些固定時間間隔后會自行取消。

那么,回到你問題中的例子。

第一個示例完全忽略請求的上下文,并從頭開始創建上下文,表面上唯一的原因是在其中攜帶內容(不好)。

第二個示例可能將上下文用于其預期目的(但我們不知道,因為我們看不到otherFunc)。


1 實際上,如果要控制的任務沒有其他策略“添加”到現有的父上下文,則不需要創建新的上下文。派生的想法是實現額外的方法來取消此特定任務中的工作,并尊重父上下文的取消。?例如,為特定任務派生的上下文可以有自己的截止日期,或者有辦法僅取消該特定上下文。
當然,可以為任務導出復雜的嵌套上下文:例如,可以從父上下文導出具有截止日期的上下文,然后可以從前者導出可取消的上下文。結果將是一個上下文被代碼明確地取消,或者當截止日期到期或當父上下文發出取消信號時被取消。


查看完整回答
反對 回復 2023-08-14
?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

你的兩個例子做了完全不同的事情。


func myHandler(w http.ResponseWriter, r *http.Request) {

  ctx := context.WithValue(context.Background(), "request", r)

  otherFunc(ctx)

}

這將創建一個新的上下文,并將請求存儲為一個值。很少(如果有的話)有任何理由這樣做。一個更慣用的解決方案是將請求傳遞給otherFunc像這樣的:


func myHandler(w http.ResponseWriter, r *http.Request) {

  otherFunc(r)

}

如果您確實需要將請求作為上下文值傳遞,則可能應該使用當前請求的上下文來執行此操作,如下所示:


func myHandler(w http.ResponseWriter, r *http.Request) {

  ctx := context.WithValue(r.Context(), "request", r)

  otherFunc(ctx)

}


查看完整回答
反對 回復 2023-08-14
  • 2 回答
  • 0 關注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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