context 包学习笔记

Context 是用来控制一个请求的生命周期,以及周期内数据共享的一个 package

数据层面

依赖 valueCtx,是一个嵌套实现的类 map 的数据结构

type valueCtx struct {
    Context
    key, val interface{}
}

通过 递归匹配,来读取最近的一次更新的值(考虑到一个请求周期内的数据应该不多,递归查询应该是可以接受的)

func (c *valueCtx) Value(key interface{}) interface{} {
    if c.key == key {
        return c.val
    }
    return c.Context.Value(key)
}

通过嵌套,来实现数据的写入。

func WithValue(parent Context, key, val interface{}) Context {
    ...
    return &valueCtx{parent, key, val}
}
生命周期

Context 生命周期的管理,或者说是退出时通知机制的实现,主要是依赖 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
}

cancelCtx 第一次被从 Context 派生出来时,后台会通过 goroutine 的方式来同步 退出 事件。 通过 select 来检测 parent 的退出,然后退出

go func() {
    select {
        case <-parent.Done():
            child.cancel(false, parent.Err())
        case <-child.Done(): // block 机制,避免立即退出
    }
}()

如果是从派生出来的对象中再次派生,则是通过 children 字段来维护派生关系. 当 parent 退出时,来主动退出所有的派生 Context

for child := range c.children {
    // NOTE: acquiring the child's lock while holding parent's lock.
    child.cancel(false, err)
}

cancel 的主要逻辑

if c.done == nil {
    c.done = closedchan
} else {
    close(c.done)
}

channel 被关闭的时候,其他所有在 select 监听的 routine 都会感知到,从而实现了通知机制。

WithDeadline 是在此基础上,增加了一个 timer 机制,通过后台来实现自己的主动退出。

type timerCtx struct {
    cancelCtx
    timer *time.Timer // Under cancelCtx.mu.

    deadline time.Time
}

c.timer = time.AfterFunc(d, func() {
            c.cancel(true, DeadlineExceeded)
        })

主要逻辑差不多就是这些

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值