path: Go SDK/src/context/context.go
结构
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
- Deadline():返回context的超时时间,若当前context未设置超时时间,则ok = false;
- Done():返回一个空结构体类型的channel,当context取消时,会关闭该通道;
- Err():返回context被取消的原因;
Value():通过key获取context中绑定的值,协程安全但不推荐使用,协程间通讯应使用channel;
context的实现
emptyCtx
空的context,虽然实现了context接口,但实现的方法内均返回nil或零值。一般在创建其它类型的context时充当根节点使用。
注:context包内的 Background和 TODO函数返回的都是一个emptyCtx实例,不同的是 todo可被静态分析工具用来验证context传递的正确性。结构及相关方法、函数 ```go 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 }
func Background() Context { return background }
func TODO() Context { return todo }
var ( background = new(emptyCtx) todo = new(emptyCtx) )
<a name="i9332"></a>
### cancelCtx
一个可随时取消的context,内部存储了一个空结构体类型的无缓冲channel,利用channel close的广播机制判断上下文是否已取消。<br />可使用WithCancel函数创建cancelCtx的实例。
- **结构及相关方法、函数**
```go
type cancelCtx struct {
// 匿名字段实现的继承关系
Context
// 互斥锁,保证协程安全
mu sync.Mutex
// 一个延迟加载的空结构类型的channel,会在Done方法内返回
// 1. 执行cancel方法时,若done==nil则赋值为全局变量 closedchan (一个已经关闭的无缓冲的channel),否则关闭done
// 2. 执行Done方法时,若done==nil,则创建一个无缓冲的channel
done chan struct{}
// 子级上下文,会在第一次执行Done方法时清空
children map[canceler]struct{}
// 第一次执行Done方法时赋值,记录上下文取消的原因。(err!=nil即表示context已取消)
err error
}
// 创建并返回cancelCtx实例和它的关闭函数
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
}
// 重写匿名字段Context的Value方法
func (c *cancelCtx) Value(key interface{}) interface{} {
}
// 重写匿名字段Context的Done方法
func (c *cancelCtx) Done() <-chan struct{} {
}
// 重写匿名字段Context的Err方法
func (c *cancelCtx) Err() error {
}
// 当前上下文的关闭方法,在WithCancel函数返回的闭包内调用
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
}
- Demo ```go import ( “context” “fmt” “time” )
func main() { ctx, cancel := context.WithCancel(context.Background())
go func() {
i := 0
for {
if closed(ctx) {
fmt.Println("上下文已关闭")
break
}
fmt.Println(i)
i++
}
}()
time.Sleep(time.Nanosecond)
cancel()
time.Sleep(time.Nanosecond)
}
func closed(ctx context.Context) bool { select { case <-ctx.Done(): return true default: return false } }
<a name="AJtp1"></a>
### timeCtx
在聚合了cancelCtx的基础上增加了Timeout机制的上下文。可使用WithTimeout和WithDeadline函数创建实例。
- **结构及相关方法、函数**
```go
type timerCtx struct {
// 匿名字段实现的继承关系
cancelCtx
// 计时器的指针,用来停止计时,防止cancel方法的二次调用
timer *time.Timer
// 上下文的超时时间
deadline time.Time
}
// 创建并返回cancelCtx实例和它的关闭函数,该上下文会在一段时间后自动取消
// 内部实际调用WithDeadline方法
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
}
// 创建并返回cancelCtx实例和它的关闭函数,该上下文在到达指定日期时取消
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
}
// 重写匿名字段cancelCtx的Deadline方法
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
}
// 当前上下的关闭方法,闭包内调用
func (c *timerCtx) cancel(removeFromParent bool, err error) {
}
- Demo ```go package main
import ( “context” “fmt” “time” )
func main() { // 等价于context.WithDeadline(context.Background(), time.Now().Add(time.Nanosecond))) ctx, _ := context.WithTimeout(context.Background(), time.Nanosecond)
go func() {
i := 0
for {
if closed(ctx) {
fmt.Println("上下文已关闭")
break
}
fmt.Println(i)
i++
}
}()
time.Sleep(time.Second)
}
func closed(ctx context.Context) bool { select { case <-ctx.Done(): return true default: return false } }
<a name="rZn8b"></a>
### valueCtx
只可存储键值对数据但不能取消的上下文。<br />_注:一个valueCtx只保存一个key和value,使用Value方法取数据时,向上递归调用Context.Value方法。_
```go
type valueCtx struct {
// 匿名字段实现的继承关系
Context
// 当前上下文保存的键值对信息
key, val interface{}
}
// 重写匿名字段Context的value方法
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}