爲什麼需要context
- context可以主要用來在goroutine中傳遞上下文信息
- 利用context關閉樹狀goroutine鏈
- 當go服務處理一個請求時,可以需要開多個goroutine,形成goroutine鏈
- 如果這個請求被取消了(例如刷新了瀏覽器或者超時了),那麼下游goroutine都應該及時退出
- 因爲他們的“工作成果”不再被需要了
- 如果不及時退出,可能會造成協程數量激增,內存耗盡
- 利用context傳遞數據
- 壞處
- 傳遞的是空接口,需要斷言,開銷較大
- 值在傳遞過程中可能被後續服務覆蓋,不易發現,也不易委會
- 常見傳遞數據類型
context的使用
- context應該作爲函數的第一個參數
- 不知道傳遞什麼context時不要傳nil,應該傳context.TODO()
func f() {
ctx1, cancel := context.WithCancel(context.Background())
defer cancel()
ctx2, _ := context.WithTimeout(ctx1, 5*time.Second)
dur := time.Now().Add(5 * time.Second)
ctx3, cancel := context.WithDeadline(ctx2, dur)
ctx4 := context.WithValue(ctx3, "key", "val")
go func() {
for {
select {
case <-ctx1.Done():
return
case <-time.Tick(time.Second):
fmt.Println(ctx4.Value("key"))
}
}
}()
time.Sleep(10 * time.Second)
}
context實現原理