为什么需要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实现原理