Context

  • 定义
    • 上下文
  • 作用
    • 并发控制中作为控制子协程的结束
    • 链路跟踪
    • 超时控制
  • 接口
    • Context
      • func Done() chan struct{}
      • func Value(key any) any
      • func Err() error
      • func Deadline() (deadline time.Time, ok bool)
    • canceler
      • 定义可取消的context
      • cancel(removeFromParent bool, err, cause error)
        • 取消context的方法,removeFromParent为是否从父context中的children移除掉,一般当前的context调用会传true,然后这个context调用它自己的children的cancel时,传false,最后由它自己把children赋值为nil即可
      • Done() <-chan struct{}
  • 实现类
    • emptyCtx
      • 实现方法都为空,String方法分别检测backgroud和todo,做对应string返回
        • backgroud context
        • todo context
    • cancelCtx
      • 结构
        • Context
        • mu sync.Metux
        • done automic.Value
        • children map[canceler]struct{}
          • 存放所有可取消的子context,用于当前context取消时,将cancel传播到子context中
        • err error
          • 第一次调用cancel()时设置
        • cause error
          • 第一次调用cancel()时设置,也即取消的理由
      • 实现
        • 创建一个cancelCtx{},将父context作为参数存放到对应的Context属性中,然后将其挂到父context的childern中,用于父context的cancel传播,也即传播context
          • 父类如果不是cancelCtx,即无法确定什么类型时,即开启一个协程监控parent的Done信号,以及自己的done信号,接收到父context的done信号会调用当前context的cancel,由它取消自身以及它可以执行取消的cancelContext子列表
        • Value(key any)的查询先判断当前key是否是&cancelctx,不是则会递归查询自己包装的父Context,直到查询到key,进行返回
        • Done(),原子获取done channel,如果为空,加锁,再获取一次,为空则make一个进行赋值
      • timerCtx
        • 结构
          • *cancelCtx
          • deadline time.Time
            • 失效时间
          • timer time.Timer
            • 存放定时器,主要作用为可进行close关闭资源,避免资源泄漏
        • 实现
          • 优先检查父context的deadline时间与当前要包装的context时间,进行对比,如果父context时间比较早失效,则只需要包装成cancelCtx返回即可
            • 为什么父context deadline时间较早时只需要包装成cancelCtx呢
              • 因为父context到期了就会传播调用子的cancel,而子cancalCtx的deadline如果时间比较长那一定不会被这个deadline时间自动触发,而一定是通过调用cancel,或者父context传播调用cancel导致失效
          • 否则包装一个timerCtx,然后同样进行context的传播。
            • 即父context为cancelCtx时,则把当前context保存到父context的children中等待后续调用
            • 如果不是cancelCtx,即启用一个协程,监听父context的Done信号,进行cancel操作。同时监听自己的done信号,以便协程在自己被cancel时退出,避免协程泄漏
          • 接下来先检查是否失效了,是的话直接cancel当前的context。否则加锁使用传进来的时间启动一个定时器,定时结束后自动执行cancel操作取消当前context,失效的话传入的error是DeadlineExceeded,其他被取消的传入的是Canceled
        • valueCtx
          • 结构就是Context加上,key和value的属性
            • 用于存放值
      • propagateCancel
        • 定义
          • 传播context的函数,里面的一个关键函数,用于传播context,以便父类cancel时可cancel掉其子context
        • 实现原理
          • 1.检查父类是否是否为可cancel的,即看done管道是否为空,不可取消的话直接返回,也即不用传播到父context
          • 2.父类可取消则先检查一下信号,判断是否父context已被取消,是的话直接取消当前context,将父error和cause,作为参数调用即可
          • 判断父context是否为cancelCtx
              • 判断父context是否被取消了,是的话直接取消子context
              • 否则将当前context加入到父context的children集合中
              • 起一个协程进行监听父context的done信号,收到则执行cancel当前的context,另外为了避免协程泄漏,还监听了自己的done信号,让自己被取消时,协程可以自然退出,避免协程泄漏