目录
功能概要
1、在一次请求过程中,可以在多(线程)进程间实现截止时间,取消信号,全局参数等功能;
Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.
2、context是按照树型结构进行组织的。已经实现的context类型包括emptyCtx,cancelCtx,timerCtx,valueCtx。一旦上层context被取消(不管是调用cancel函数,还是截止时间到期),下层的context均会收到取消信号。至于业务系统在context收到取消信号后何时停止剩余任务的执行,完全取决于业务系统本身,二者是异步的关系。
考虑下面这种情况:假如主协程中有多个任务1, 2, …m,主协程对这些任务有超时控制;而其中任务1又有多个子任务1, 2, …n,任务1对这些子任务也有自己的超时控制,那么这些子任务既要感知主协程的取消信号,也需要感知任务1的取消信号。
Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled.
3、WithCancel函数会返回一个可以取消的对象cancelCtx;WithDeadline和WithTimeout函数会返回一个有截止时间的对象timerCtx。除此以外,还会返回一个回掉函数CancelFunc做取消使用。
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived Context (the child) and a CancelFunc. Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers. Failing to call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are used on all control-flow paths.
4、Context是线程安全的
The same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines.
接口
type Context interface {
Deadline() (deadline time.Time, ok bool). // 返回任务的截止时间(channel关闭),ok为false表示没有截止时间
Done() <-chan struct{} // 返回channel,其表示context被关闭,包括两种情形(1、cancel函数被调用,2、截止时间到达)
Err() error // channel关闭的原因(1、取消,2、截止时间)
Value(key interface{}) interface{} // 每个context可以关联一组key,value
}
root节点
// An emptyCtx is never canceled, has no values, and has no deadline.
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done() <-chan struct{} {
return nil
}
func (*emptyCtx) Err() error {
return nil
}
func (*emptyCtx) Value(key interface{}) interface{} {
return nil
}
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
func Background() Context {
return background
}
func TODO() Context {
return todo
}
功能节点
valueCtx
该节点的主要功能是允许携带一对key,value
// 节点定义
type valueCtx struct {
Context
key, val interface{}
}
// 生成节点
func WithValue(parent Context, key, val interface{}) Context {
if key == nil {
panic("nil key")
}
if !reflectlite.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &valueCtx{parent, key, val}
}
cancelCtx
该节点提供了一个可取消的函数,供业务系统调用
// 节点定义
type cancelCtx struct {
Context
mu sync.Mutex // protects following fields
done chan struct{} // created lazily, closed by first cancel call
children map[canceler]struct{} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
// 取消函数接口
type CancelFunc func()
// 生成节点
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
propagateCancel(parent, &c) // 将本节点和父节点关联起来,这样一旦父节点取消,本节点也一并被取消
return &c, func() { c.cancel(true, Canceled) }
}
timerCtx
该节点的主要功能是提供一个截止时间,一旦截止时间到期,context会自动被取消
// 节点定义
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
// 生成节点
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
if cur, ok := parent.Deadline(); ok && cur.Before(d) {
// The current deadline is already sooner than the new one.
return WithCancel(parent)
}
c := &timerCtx{
cancelCtx: newCancelCtx(parent),
deadline: d,
}
propagateCancel(parent, c)
dur := time.Until(d)
if dur <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
return c, func() { c.cancel(false, Canceled) }
}
c.mu.Lock()
defer c.mu.Unlock()
if c.err == nil {
c.timer = time.AfterFunc(dur, func() {
c.cancel(true, DeadlineExceeded)
})
}
return c, func() { c.cancel(true, Canceled) }
}