背景關系 Context
背景關系 context.Context 是用來設定截止日期、同步信號,傳遞請求相關值的結構體,
背景關系與 Goroutine 有比較密切的關系,
context.Context 是 Go 語言中獨特的設計,在其他編程語言中我們很少見到類似的概念,

context.Context 是 Go 語言在 1.7 版本中引入標準庫的介面,該介面定義了四個需要實作的方法,其中包括:
Deadline — 回傳 context.Context 被取消的時間,也就是完成作業的截止日期;
Done — 回傳一個 Channel,這個 Channel 會在當前作業完成或者背景關系被取消之后關閉,多次呼叫 Done 方法會回傳同一個 Channel;
Err — 回傳 context.Context 結束的原因,它只會在 Done 回傳的 Channel 被關閉時才會回傳非空的值;
如果 context.Context 被取消,會回傳 Canceled 錯誤;
如果 context.Context 超時,會回傳 DeadlineExceeded 錯誤;
Value — 從 context.Context 中獲取鍵對應的值,對于同一個背景關系來說,多次呼叫 Value 并傳入相同的 Key 會回傳相同的結果,該方法可以用來傳遞請求特定的資料;
我們可以通過一個代碼片段了解 context.Context 是如何對信號進行同步的,在這段代碼中,我們創建了一個過期時間為 1s 的背景關系,并向背景關系傳入 handle 函式,該方法會使用 500ms 的時間處理傳入的『請求』:

因為過期時間大于處理時間,所以我們有足夠的時間處理該『請求』,運行上述代碼會列印出如下所示的內容:

handle 函式沒有進入超時的 select 分支,但是 main 函式的 select 卻會等待 context.Context 的超時并列印出 main context deadline exceeded,
如果我們將處理『請求』時間增加至 1500ms,整個程式都會因為背景關系的過期而被中止,

相信這兩個例子能夠幫助大家理解 context.Context 的使用方法和設計原理 — 多個 Goroutine 同時訂閱 ctx.Done() 管道中的訊息,一旦接收到取消信號就立刻停止當前正在執行的作業,
context.WithCancel
函式能夠從 context.Context 中衍生出一個新的子背景關系并回傳用于取消該背景關系的函式(CancelFunc),一旦我們執行回傳的取消函式,當前背景關系以及它的子背景關系都會被取消,所有的 Goroutine 都會同步收到這一取消信號,

context.newCancelCtx
函式將傳入的背景關系包裝成私有結構體 context.cancelCtx;
context.propagateCancel 會構建父子背景關系之間的關聯,當父背景關系被取消時,子背景關系也會被取消:

上述函式總共與父背景關系相關的三種不同的情況:
當 parent.Done() == nil,也就是 parent 不會觸發取消事件時,當前函式會直接回傳;
當 child 的繼承鏈包含可以取消的背景關系時,會判斷 parent 是否已經觸發了取消信號;
如果已經被取消,child 會立刻被取消;
如果沒有被取消,child 會被加入 parent 的 children 串列中,等待 parent 釋放取消信號;
在默認情況下運行一個新的 Goroutine 同時監聽 parent.Done() 和 child.Done() 兩個 Channel
在 parent.Done() 關閉時呼叫 child.cancel 取消子背景關系;
context.propagateCancel
作用是在 parent 和 child 之間同步取消和結束的信號,保證在 parent 被取消時,child 也會收到對應的信號,不會發生狀態不一致的問題,
context.cancelCtx 實作的幾個介面方法也沒有太多值得分析的地方,該結構體最重要的方法是 cancel,這個方法會關閉背景關系中的 Channel 并向所有的子背景關系同步取消信號:

除了 context.WithCancel 之外,context 包中的另外兩個函式 context.WithDeadline 和 context.WithTimeout 也都能創建可以被取消的計時器背景關系 context.timerCtx:

context.WithDeadline
方法在創建 context.timerCtx 的程序中,判斷了父背景關系的截止日期與當前日期,并通過 time.AfterFunc 創建定時器,當時間超過了截止日期后會呼叫 context.timerCtx.cancel 方法同步取消信號,
context.timerCtx 結構體內部不僅通過嵌入了context.cancelCtx 結構體繼承了相關的變數和方法,還通過持有的定時器 timer 和截止時間 deadline 實作了定時取消這一功能:
context.timerCtx.cancel 方法不僅呼叫了 context.cancelCtx.cancel,還會停止持有的定時器減少不必要的資源浪費,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/229261.html
標籤:區塊鏈
上一篇:Uniswap只能買不能賣無法賣出/教程defi/設定黑白名單/交易次數/交易最小值最大值/防止APY合約套利機器人等/手把手教uniswap教程
下一篇:Golang 之 中間件
