簡介
context是Go中廣泛使用的程序包,由Google官方開發在1.7版本引入。它用來簡化在多個go routine傳遞上下文數據、(手動/超時)中止routine樹等操作,比如,官方http包使用context傳遞請求的上下文數據,gRpc使用context來終止某個請求產生的routine樹。由于它使用簡單,現在基本成了編寫go基礎庫的通用規范。
1.使用入門:kv存儲
- context在整體上看就是一個樹,每個節點只能存儲一個kv對
- Background() 創建一個根節點
- WithValue() 父context衍生一個子context,并將key/value對保存到子節點。
- Value() 從某個節點取出Value,子節點可以取到父節點的kv。
代碼示例:
func main() {
root := context.Background()
ctx1 := context.WithValue(root, "key1", "value1")
ctx2 := context.WithValue(ctx1, "key2", "value2")
fmt.Println(ctx1.Value("key1"))
fmt.Println(ctx1.Value("key11"))
fmt.Println(ctx2.Value("key2"))
}
value1
<nil>
value2
2. 控制并發(goroutine)
當context節點close時,會觸發 Done() 操作,goroutine可以接收次消息通知。
func main() {
root := context.Background()
//ctx1, cancel := context.WithDeadline(root, time.Now().Add(6 * time.Second))
ctx1, cancel := context.WithCancel(root)
ctx2 := context.WithValue(ctx1, "key2", "value2")
go watch(ctx2)
time.Sleep(10 * time.Second)
fmt.Println("通知監控停止")
cancel()
time.Sleep(5 * time.Second)
}
func watch(ctx context.Context) {
for {
select {
case <- ctx.Done():
fmt.Println(ctx.Value("key2"), "監控退出了。")
return
default:
fmt.Println(ctx.Value("key2"), "go rountine 監控中。。。")
time.Sleep(2 * time.Second)
}
}
}