讀這篇之前最好先看完 Pipelines and cancellation
補完一些前提知識。
Go Concurrency Patterns: Context
Go Concurrency Patterns: Context
Introduction
在 Go servers,每一個 request 交由他的 goroutine 處理。
Request handlers
通常會開啟額外的 goroutines 去存取後端,如資料庫 和 RPC 服務。
運作在 request 中的 goroutines,通常會需要存取特定的值(request-specific values)
,如終端使用者 ID,authorization tokens,request 的期限(deadline)
。
當一個 request 被取消 或 timeout,所有運作在這個 request 的 goroutines 應當快點結束,因此系統能多回收點資源來用。
在 Google,我們開發 context package,他可以很簡單的傳送 request 相關的值(request-scoped values)
,取消訊號,and deadlines across API boundaries to all the goroutines involved in handling a request.
Context
1 | // A Context carries a deadline, cancelation signal, and request-scoped values |
Done 方法
回傳個 channel,這個 channel 扮演著給 funcs 的 取消訊號
:
- 當 channel 關閉後,funcs 應當拋棄他們的工作並
return
。
Err 方法
會回傳 error,他會解釋說為什麼這個 Context 被取消。
The Pipelines and Cancelation 這篇提到 Done channel
更多的說明。
Context 並沒有 取消方法
,原因如同 Done channel
是 receive-only:
func 接收取消訊號通常不是 the one that sends the signal
特別是,當一個母操作開啟了子操作 goroutines,子操作不應該有能力把母操作關閉。
此外,WithCancel function
提供一個取消 new Context value
的方式。
Context 分給多個 goroutines 使用是安全低。
他可以傳出單一的 Context 給任意數量的 goroutines 然後 取消那個 Context 來發出訊號給所有 goroutines。
Deadline method
允許 funcs 決定他們是否該開始工作;
如果只有剩餘一點點時間,it may not be worthwhile。
Code 可能也使用 deadline 來設定 I/O 操作的 timeout。
Value
允許 Context 攜帶 request-scoped data
。
這個資料必須能安全的同時給多個 goroutines 使用。
Derived contexts
這個 Lib 提供了 funcs 從既有的 Context 推導出新的 Context Value。
這個值是個樹 form a tree
:
當一個 Context 被取消後,其下的分支也會被關閉。
Background
是所有 Context 的 root; 且他絕不會被關閉:
1 | // Background returns an empty Context. It is never canceled, has no deadline, |
WithCancel and WithTimeout
回傳推導 Context values,他能夠比 母 Context
更快被關閉。
當 request handler returns 後,request 相關聯的 Context 會被取消。
當使用多個複製品(replicas),用 WithCancel
來取消冗餘(redundant)的 requests 也相當有用。
用 WithTimeout
設定 request 給後端 server 的 deadline 是有用的:
1 | // WithCancel returns a copy of parent whose Done channel is closed as soon as |