简介
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)
}
}
}
网友评论