golang context包學習分享

2021-10-11 02:06:31 字數 3089 閱讀 4805

context.context 是 go 語言中獨特的設計,在其他程式語言中我們很少見到類似的概念。

上下文與 goroutine 有比較密切的關係。

上下文 context.context 是用來設定截止日期、同步訊號,傳遞請求相關值的結構體。

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.context 中衍生出乙個新的子上下文並返回用於取消該上下文的函式(cancelfunc)。

一旦我們執行返回的取消函式,當前上下文以及它的子上下文都會被取消,所有的 goroutine 都會同步收到這一取消訊號。

函式將傳入的上下文包裝成私有結構體 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 取消子上下文

作用是在 parent 和 child 之間同步取消和結束的訊號,保證在 parent 被取消時,child 也會收到對應的訊號,不會發生狀態不一致的問題。

context.cancelctx 實現的幾個介面方法也沒有太多值得分析的地方,該結構體最重要的方法是 cancel,這個方法會關閉上下文中的 channel 並向所有的子上下文同步取消訊號:

除了 context.withcancel 之外,context 包中的另外兩個函式context.withdeadlinecontext.withtimeout也都能建立可以被取消的計時器上下文 context.timerctx:

方法在建立 context.timerctx 的過程中,判斷了父上下文的截止日期與當前日期,並通過 time.afterfunc 建立定時器,當時間超過了截止日期後會呼叫 context.timerctx.cancel 方法同步取消訊號。

context.timerctx 結構體內部不僅通過嵌入了context.cancelctx 結構體繼承了相關的變數和方法,還通過持有的定時器 timer 和截止時間 deadline 實現了定時取消這一功能:

方法不僅呼叫了 context.cancelctx.cancel,還會停止持有的定時器減少不必要的資源浪費。

golang context強制提前退出

golang中context包實現提前退出 以前不知道怎麼寫的,一直無法退出,還以為程式就是無法提前退出。下面的程式,request休眠100s,然後在另外乙個goroutine中,3s後退出所有context import context log sync time func request va...

Golang Context的常規操作

golang context的常規操作 context是go的併發程式設計的常用模式,可以通過context來處理超時,取消任務等一系列操作 func main childctx,i time.after time.second 2 2秒後開始關閉 cancel 關掉paraentcontext,會...

伺服器開發利器golangcontext用法詳解

伺服器開發利器golangcontext用法詳解。在go伺服器中,對於每個請求的request都是在單獨的goroutine中進行的,處理乙個request也可能設計多個goroutine之間的互動,使用context可以使開發者方便的在這些goroutine裡傳遞request相關的資料 取消go...