前言
Golang 中的 context 是Go 语言在 golang 1.7 发布时新增的标注包。
目的是增强Golang 开发中并发控制技术
简单来说当一个服务启动时候,可能由此服务派生出多层级的goroutine ,但本质上来讲每个层级的goroutine 都是平行调度使用,不存在goroutine的 父子关系
,当其中一个goroutine执行的任务被取消了或者处理超时了,那么其他被启动起来的goroutine 都应该迅速退出,另外多个多层的goroutine 想传递请求域的数据该如何处理?
如果单个请求的goroutine 结构比较简单,或者处理起来不麻烦,但如果启动的goroutine 是多个并且结构层次很深,那么光是保障每个goroutine 正常退出也不容易了。
Context 可以跟踪goroutine 的调用,在内部维护一个调用树,通过这个调用树可以在传递超时或者退出通知,还能在调用树中传递元数据
context 的中文翻译是上下文,可以理解为context 管理了一组呈现树状结构的goroutine,让每个goroutine 都拥有相同的上下文,并且可以在这个上下文中传递数据。
Context interface
context 实际上只是定义的四个方法的接口,凡是实现了该接口的都称为一种context
emptyCtx
可以看到emptyCtx 实现了context 接口,但是其实现的方法都是空nil,那么我们就可以知道其实emptyCtx是不具备任何实际功能的,那么它存在的目的是什么?
emptyCtx 存在的意义是作为Context 对象树根节点的root节点
在context 包中提供了 Background() 和TODO() 两个函数,这两个函数都是返回的都是emptyCtx实例。通常我们使用他们构建Context 的根节点,有了root根节点之后就可以同Context.go 包中提供的其他包装函数创建具有意义的context实例,并且context实例的创建都是以上一个context 实例对象作为参数的(所以必须要有一个根节点),最终形成一个树状的管理结构。
cancelCtx
定义了cancelCtx 类型的结构体其中字段 children 记录派生的 child ,当该类型的context(上下文) 被执行的cancel是会将所有的派生的child 都执行cancel。
valueCtx
通过valueCtx 结构知道仅是在context 的基础上增加了元素key 和 value 通常用于在层级协程之间传递数据。
timeCtx
在cancelCtx 的基础上增加了字段timer 和deadline
timer触发自动cancel 的定时器
deadline 标识最后执行cancel的时间
context.go 包中提供了4个以 with 开头的函数这几个函数的主要功能是实例化不同类型的context
- 通过Background() 和 TODO() 创建empty实例,通常作为根节点
- 通过WithCancel() 创建cancelCtx 实例
- 通过WithValue() 创建valueCtx实例
- 通过WithDeadline 和 WithTimeout 创建timerCtx 实例