编程语言中的 Context
Context 的直接翻译是上下文或环境。在编程语言中,翻译成运行环境更合适。
比如一段程序,在执行之初,我们可以设定一个环境参数:最大运行时间,一旦超过这个时间,程序也应该随之终止。
在 golang 中, Context 被用来在各个 goroutine 之间传递取消信号、超时时间、截止时间、key-value等环境参数。
golang 中的 Context 的实现
golang中的Context包很小,除去注释,只有200多行,非常适合通过源码阅读来了解它的设计思路。
注:本文中的golang 均指 go 1.14
接口 Context 的定义
golang 中 Context 是一个接口类型,具体定义如下:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{
}
Err() error
Value(key interface{
}) interface{
}
}
Deadline()
Deadline() 返回的是当前 Context 生命周期的截止时间。
Done()
Done() 返回的是一个只读的 channel,如果能从这个 channel 中读到任何值,则表明context的生命周期结束。
Err()
这个比较简单,就是返回异常。
Value(key interface{})
Value(key interface{}) 返回的是 Context 存储的 key 对应的 value。如果在当前的 Context 中没有找到,就会从父 Context 中寻找,一直寻找到最后一层。
4种基本的context类型
类型 | 说明 |
---|---|
emptyCtx | 一个没有任何功能的 Context 类型,常用做 root Context。 |
cancelCtx | 一个 cancelCtx 是可以被取消的,同时由它派生出来的 Context 都会被取消。 |
timerCtx | 一个 timeCtx 携带了一个timer(定时器)和截止时间,同时内嵌了一个 cancelCtx。当 timer 到期时,由 cancelCtx 来实现取消功能。 |
valueCtx | 一个 valueCtx 携带了一个 key-value 对,其它的 key-value 对由它的父 Context 携带。 |
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
}
看 emptyCtx 很轻松,因为它什么都没做,仅仅是实现了 Context 这个接口。在 context 包中,有一个全局变量 background,值为 new(emptyCtx),它的作用就是做个跟 Context。其它类型的 Context 都是在 background 的基础上扩展功能。
cancelCtx 定义及实现
先看下 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
}
// 创建
func Wit