2 回答

TA貢獻2011條經驗 獲得超2個贊
您可能會錯過上下文的要點 - 據說是由于您正在處理的 HOWTO 很差。
在上下文中攜帶任意值的可能性實際上是這種類型的一個缺陷,其設計者對此感到遺憾,因為它創建了一種反模式(處理上下文作為某種狀態的正確方法是明確地擁有一組值)傳遍了)。
上下文存在的主要原因是它們提供了信號的樹狀傳播(在上下文的情況下是取消或“完成”)。所以上下文背后的原始想法如下:
“根”上下文對象是為傳入請求創建的。
需要代表請求執行的每個“任務”都與其自己的上下文相關聯,該上下文源自請求的上下文。
這些任務可能會產生其他任務等等。
正如您所看到的,形成了“工作單元”的層次結構,鏈接到對象,這是這些單元存在和執行的原因。
當傳入請求被取消時(例如,客戶端的套接字斷開連接),與其關聯的上下文對象也會被取消,然后所有鏈接的任務都會收到它,因為它從生成的上下文樹的根向下傳播到其離開——確保為請求執行的所有任務(最終)被取消。
當然,為了使其發揮作用,每個“任務”(通常是一個執行某些操作的 goroutine)都需要從傳遞給它的上下文中“監聽”該“完成”信號。
上下文還支持開箱即用的超時,因此您可以創建一個上下文,該上下文在經過一些固定時間間隔后會自行取消。
那么,回到你問題中的例子。
第一個示例完全忽略請求的上下文,并從頭開始創建上下文,表面上唯一的原因是在其中攜帶內容(不好)。
第二個示例可能將上下文用于其預期目的(但我們不知道,因為我們看不到otherFunc
)。
1 實際上,如果要控制的任務沒有其他策略“添加”到現有的父上下文,則不需要創建新的上下文。派生的想法是實現額外的方法來取消此特定任務中的工作,并尊重父上下文的取消。?例如,為特定任務派生的上下文可以有自己的截止日期,或者有辦法僅取消該特定上下文。
當然,可以為任務導出復雜的嵌套上下文:例如,可以從父上下文導出具有截止日期的上下文,然后可以從前者導出可取消的上下文。結果將是一個上下文被代碼明確地取消,或者當截止日期到期或當父上下文發出取消信號時被取消。

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)
}
- 2 回答
- 0 關注
- 190 瀏覽
添加回答
舉報