Go 併發 : Context

翻譯自:Go Concurrency Patterns: Context
地址:https://blog.golang.org/context

簡介

在Go server端,每個請求都是通過新起goroutine來處理。請求處理程序通常會啓動其他goroutine來訪問後端,例如數據庫和RPC服務。處理該請求的goroutine集合通常需要訪問特定於請求的值,例如最終用戶的身份,授權令牌和請求的時限。當一個請求被取消或超時時,處理該請求的所有goroutine應該迅速退出,以便系統可以回收他們正在使用的資源。

在Google,我們開發了一個Context包,可以輕鬆地跨API邊界將請求範圍(request-scoped)的值,取消信號和截止日期(deadlines)傳遞給處理請求的所有goroutine。該軟件包可作爲Context公開使用。本文將介紹如何使用該package。

Context

Context包的核心是Context類型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Context跨API邊界攜帶期限(deadline)、取消信號和請求範圍(request-scoped)的值。Context的方法是協程安全的。
type Context interface {
    // Done返回一個channel,該channel在Context被取消或超時時關閉。
    Done() <-chan struct{}

    // Err表示在Done channel關閉後取消此Context的原因。
    Err() error

    // Deadline返回Context將被取消的時間(如果有的話)。
    Deadline() (deadline time.Time, ok bool)

    // Value返回與key關聯的值(如果沒有,返回nil)。
    Value(key interface{}) interface{}
}

更詳細的介紹,參見godoc:https://golang.org/pkg/context/

Done方法返回一個channel,作爲代表Context運行的函數的取消信號:當channel關閉時,函數應該放棄它們的工作並返回。Err方法返回一個錯誤,指示Context被取消的原因。

因爲Done channel只用於接收的原因,Context沒有取消方法:接收取消信號的方法與發送信號方法往往不是同一個。特別是,當父操作(parent operation)爲子操作(sub-operations)啓動goroutines時,這些子操作應該不能取消父操作。相反,WithCancel函數(如下所述)提供了一種取消新的上下文值的方法。

Context是協程安全的。代碼中可以將單個Context傳遞給任意數量的goroutine,並在取消該Context時可以將信號傳遞給所有的goroutine。

最後期限(Deadline)方法允許函數決定他們是否應該開始工作;如果剩下的時間太少,可能就不值得了。代碼也可以使用期限(Deadline)來設置I/O操作的超時。

值(Value)允許Context攜帶請求範圍(request-scoped)的數據。該數據必須是協程安全的,以便多個goroutine可以同時使用。

Derived contexts

Context包提供了從現有Context值派生新Context值的函數。這些值形成一個樹:當一個Context被取消時,從它派生的所有Context也被取消。

Background是所有Context樹的根;它永遠不會被取消:

1
2
3
// Background返回一個空Context。它永遠不會被取消,沒有截止日期,也沒有值。
// 後臺通常用於main、init和測試,並作爲傳入請求的頂級上下文。
func Background() Context

WithCancel和WithTimeout返回派生的Context值,該值可以比父Context早被取消。請求處理程序返回時,通常會取消與傳入請求關聯的Context。使用多個副本時,WithCancel對於取消冗餘請求也很有用。WithTimeout對於設置對後端服務器的請求的最後期限很有用:

1
2
3
4
5
6
7
8
9
10
11
// WithCancel返回parent的副本,該副本的parent channel在parent結束後立即關閉。done關閉或調用cancel。
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

// CancelFunc取消Context。
type CancelFunc func()

// WithTimeout返回父對象的副本,該父對象的Done channel會在父對象關閉後立即關閉。
// 調用cancel或超時,關閉Done。
// 新的上下文截止日期是now + timeout和父級截止日期(如果有)中的較早者。
// 如果計時器仍在運行,則取消功能將釋放其資源。
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

WithValue提供了一種將請求範圍的值與Context關聯的方法:

1
2
// WithValue returns a copy of parent whose Value method returns val for key.
func WithValue(parent Context, key interface{}, val interface{}) Context

< END >

 or 

            

推薦閱讀:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章