path: Go SDK/src/context/context.go

结构

  1. type Context interface {
  2. Deadline() (deadline time.Time, ok bool)
  3. Done() <-chan struct{}
  4. Err() error
  5. Value(key interface{}) interface{}
  6. }
  • Deadline():返回context的超时时间,若当前context未设置超时时间,则ok = false;
  • Done():返回一个空结构体类型的channel,当context取消时,会关闭该通道;
  • Err():返回context被取消的原因;
  • Value():通过key获取context中绑定的值,协程安全但不推荐使用,协程间通讯应使用channel;

    context的实现

    image.png

    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) )

  1. <a name="i9332"></a>
  2. ### cancelCtx
  3. 一个可随时取消的context,内部存储了一个空结构体类型的无缓冲channel,利用channel close的广播机制判断上下文是否已取消。<br />可使用WithCancel函数创建cancelCtx的实例。
  4. - **结构及相关方法、函数**
  5. ```go
  6. type cancelCtx struct {
  7. // 匿名字段实现的继承关系
  8. Context
  9. // 互斥锁,保证协程安全
  10. mu sync.Mutex
  11. // 一个延迟加载的空结构类型的channel,会在Done方法内返回
  12. // 1. 执行cancel方法时,若done==nil则赋值为全局变量 closedchan (一个已经关闭的无缓冲的channel),否则关闭done
  13. // 2. 执行Done方法时,若done==nil,则创建一个无缓冲的channel
  14. done chan struct{}
  15. // 子级上下文,会在第一次执行Done方法时清空
  16. children map[canceler]struct{}
  17. // 第一次执行Done方法时赋值,记录上下文取消的原因。(err!=nil即表示context已取消)
  18. err error
  19. }
  20. // 创建并返回cancelCtx实例和它的关闭函数
  21. func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
  22. }
  23. // 重写匿名字段Context的Value方法
  24. func (c *cancelCtx) Value(key interface{}) interface{} {
  25. }
  26. // 重写匿名字段Context的Done方法
  27. func (c *cancelCtx) Done() <-chan struct{} {
  28. }
  29. // 重写匿名字段Context的Err方法
  30. func (c *cancelCtx) Err() error {
  31. }
  32. // 当前上下文的关闭方法,在WithCancel函数返回的闭包内调用
  33. func (c *cancelCtx) cancel(removeFromParent bool, err error) {
  34. }
  • Demo ```go import ( “context” “fmt” “time” )

func main() { ctx, cancel := context.WithCancel(context.Background())

  1. go func() {
  2. i := 0
  3. for {
  4. if closed(ctx) {
  5. fmt.Println("上下文已关闭")
  6. break
  7. }
  8. fmt.Println(i)
  9. i++
  10. }
  11. }()
  12. time.Sleep(time.Nanosecond)
  13. cancel()
  14. time.Sleep(time.Nanosecond)

}

func closed(ctx context.Context) bool { select { case <-ctx.Done(): return true default: return false } }

  1. <a name="AJtp1"></a>
  2. ### timeCtx
  3. 在聚合了cancelCtx的基础上增加了Timeout机制的上下文。可使用WithTimeout和WithDeadline函数创建实例。
  4. - **结构及相关方法、函数**
  5. ```go
  6. type timerCtx struct {
  7. // 匿名字段实现的继承关系
  8. cancelCtx
  9. // 计时器的指针,用来停止计时,防止cancel方法的二次调用
  10. timer *time.Timer
  11. // 上下文的超时时间
  12. deadline time.Time
  13. }
  14. // 创建并返回cancelCtx实例和它的关闭函数,该上下文会在一段时间后自动取消
  15. // 内部实际调用WithDeadline方法
  16. func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
  17. }
  18. // 创建并返回cancelCtx实例和它的关闭函数,该上下文在到达指定日期时取消
  19. func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
  20. }
  21. // 重写匿名字段cancelCtx的Deadline方法
  22. func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
  23. }
  24. // 当前上下的关闭方法,闭包内调用
  25. func (c *timerCtx) cancel(removeFromParent bool, err error) {
  26. }
  • 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)

  1. go func() {
  2. i := 0
  3. for {
  4. if closed(ctx) {
  5. fmt.Println("上下文已关闭")
  6. break
  7. }
  8. fmt.Println(i)
  9. i++
  10. }
  11. }()
  12. time.Sleep(time.Second)

}

func closed(ctx context.Context) bool { select { case <-ctx.Done(): return true default: return false } }

  1. <a name="rZn8b"></a>
  2. ### valueCtx
  3. 只可存储键值对数据但不能取消的上下文。<br />_注:一个valueCtx只保存一个key和value,使用Value方法取数据时,向上递归调用Context.Value方法。_
  4. ```go
  5. type valueCtx struct {
  6. // 匿名字段实现的继承关系
  7. Context
  8. // 当前上下文保存的键值对信息
  9. key, val interface{}
  10. }
  11. // 重写匿名字段Context的value方法
  12. func (c *valueCtx) Value(key interface{}) interface{} {
  13. if c.key == key {
  14. return c.val
  15. }
  16. return c.Context.Value(key)
  17. }