context 主要用来在goroutine 之间传递上下文信息,包括取消信号、超时时间、截止时间、k-v等。标准库的许多接口加上了 context 参数,来实现并发控制和超时控制。
一、源码解析
1. 接口
(1)Context
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
该接口定义了4个方法,分别是:
- Deadline():返回 context 的截止时间及是否会被取消,根据这个时间决定是否执行接下来的操作
- Done():当 context 被取消或到了 deadline 时,返回一个被关闭的 channel
- Err():返回 channel 被关闭的原因
- Value():获取之前设置的 key 对应的value
(2)canceler
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
该接口将 context 与取消操作分离开
2. 结构体
(1)emptyCtx
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
}
给出的一个默认实现,该context不会被取消、没有截止时间、没有存键值对,它被包装成两个结构,并提供导出函数对外公开
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
func Background() Context {
return background
}
func TODO() Context {
return todo
}
- background:通常用在 main 函数,作为所有 context 的根节点 <