golang 1.7之后引入了context.
首先看看context,下边是golang sdk源代码中context内容,可以发现他是一个接口,通过定义一种规范,来规定context操作方法.
// 上下文是一个接口.
// 这个接口中声明了4个方法.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
// 这个方法在timerCtx类中实现.
// 主要服务于定时类型的context服务.
// 通过设置截止时间戳,来规定context的有效期间.
// 只有通过WithDeadline或者WithTimeout才能操作Deadline.
Deadline() (deadline time.Time,ok bool)
// 判断context是否被关闭
// 如果context被取消,则Done返回nil,反之,返回一个有效的地址.
Done() <-chan struct{}
// 当context被取消时,返回一个非nil的值.
// 如果context没有取消,返回nil
Err() error
// 主要用户valueCtx
// 用来存储context中的值.
// 只有通过WithValue得到的context,才能操作Value
// 通过WithValue创建出来的context,只能通过父级context才能使用上边的3个方法.
Value(key interface{}) interface{}
}
源代码中实现有两种类,第一种是实现了Context接口,第二种是组合了Context接口.对于这两种方式,是有区别的:
1. 实现了Context接口的类,可以访问Context所有方法
2. 组合了Context接口的类,不一定Context所有方法都可以正常使用.
实现了Context接口的类
emptyCtx实现了context接口.
// An emptyCtx is never canceled,has no values,and has no deadline. It is not
// struct{},since vars of this type must have distinct addresses.
type emptyCtx int
下边定义了两个空值context
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
默认情况下,已经存在了上边两个空的context.在后边的应用中,可以将空的context设置为parent context来使用.
组合了Context接口的类
下边来具体介绍下上述3个组合了Context的类.
cancelCtx类
type cancelCtx struct {
Context
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
children map[canceler]bool // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
WithCancel(parent context) (ctx Context,cancel CancelFunc)
1. 通过函数WithCancel,生成了cancelCtx的实例,但是这个函数的返回值是Context.所以cancelCtx被赋值给Context后,对白只能暴露出Context的方法.
2. .cancelCtx实现了Context的Done方法.Done可以判断这个context是否被取消. WithCancel返回了一个cancelFunc,通过cancelFunc可以取消这个context,以及这个context的子context.
timerCtx类
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
这个类组合了cancelCtx.这个类是在cancelCtx的基础上,扩展了定时器功能.通过定时器,可以自动的去取消context.
1. 可以通过WithDeadline与WithTimeout来创建timerCtx实例,与WithCancel一样,这两个函数的返回值也是Context.
WithTimeout(parent Context,timeout time.Duration) (Context,CancelFunc)
WithDeadline(parent Context,deadline time.Time) (Context,CancelFunc)
WithTimeout是对WithDeadline的更进一层封装.WithDeadline是设定具体的到日时间戳,而WithTimeout是在当前时间的基础上加上一个值,得到到期时间戳,接着调用了WithDeadline.
valueCtx类
type valueCtx struct {
Context
key,val interface{}
}
WithValue(parent Context,key,val interface{}) Context
通过这个函数来创建valueCtx的实例.通过这个函数创建出来的Context,只能操作Value.但是可以通过父级context操作是否关闭当前的context.
总结
context类似于一个家族图谱.一层一层的继承.