go的context是乙個設計非常精巧的介面,我們可以使用它非常方便進行上下文的值傳遞,同時也控制goroutine
的生命週期。
context提供了乙個withvalue
函式,可將一對 key/value 的值存放到context中
func
testcontextwithvalue
(t *testing.t)
很多第三方類庫都會有乙個超時時間,當執行某個操作超過我們設定時間時,就不再繼續進行操作了,而是返回乙個超時錯誤,他們實現的方式基本也都是使用context的超時取消功能。
func
testcontextwithtimeout
(t *testing.t)
}
當我們做某些對時間有限制的邏輯時,比如到某時刻停止某個協程時,就可以使用該函式。
func
testcontextwithdeadline
(t *testing.t)
}
context 提供了乙個withcancel的函式可以幫我們手動取消該context,該函式會返回乙個cancel方法,我們呼叫此方法即可。
func
testcontextwithcancel
(t *testing.t)
}
其實無論是超時取消,定時取消還是手動取消,它本質都是往context的done通道裡面放乙個值罷了,我們通過監聽done通道來達到實現這些目的。原始碼
通過原始碼我們可以看到context的value方法是通過遞迴去獲取key的值得,當前的context如果獲取不到時,它會去獲取該context的父context,直到獲取到或父context為nil
時為止,所以一旦子context的key與父context的key相同時,子context會覆蓋掉父context中key的值,我們通過 子context.value(「key」) 方法只能拿到子context的,而拿不到父context的
測試一下
當我們呼叫grpc介面來傳遞context裡面的key/value時,我們會發現下游的grpc介面是獲取不到我們的key/value的,這是因為grpc內部對context做了轉換導致的,解決方式是我們可以將資訊放到metadata裡面,然後grpc下游介面可以從metadata裡面獲取資訊。
import
("context"
"fmt"
"google.golang.org/grpc/metadata"
"testing"
)func
testcontextwithmetadata
(t *testing.t)
)// 存放metadata裡
newctx := metadata.
newoutgoingcontext
(ctx, md)
var user string
// 從metadata取
這種情況下,被呼叫的 rpc 是收不到請求的。 pinggo 先return 掉了,整個 context 已經處於 cancel 的狀態了。
除此之外,像gin框架,也會有類似的問題
解決方案
重新建立乙個 context,將該context作為呼叫rpc 傳遞的引數
Go語言中使用JSON
encode 將乙個物件編碼成json資料,接受乙個inte ce 物件,返回byte和error func marshal v inte ce byte,error marshal函式將會遞迴遍歷整個物件,依次按成員型別對這個物件進行編碼,型別轉換規則如下 bool型別 轉換為json的boole...
Go語言中defer的使用
func print a int func add a,b int int fmt.println add 4,3 上面這段 defer語句輸出的是4,add返回的值是7。defer可以用於檔案的開啟和關閉,鎖的開啟和關閉。package ioutil func readfile filename ...
Go語言中Range的使用
go 語言中 range 關鍵字用於 for 迴圈中迭代陣列 array 切片 slice 通道 channel 或集合 map 的元素。在陣列和切片中它返回元素的索引和索引對應的值,在集合中返回 key value 對。package main import fmt func main sum 0...