golang context 源码阅读

golang context 源码阅读,第1张

概述Context 派生: ctx, _ := context.WithTimeout(context.Background(), (10 * time.Second)) 源码分析: // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).//// Canceling this context releases re Context 派生:
ctx,_ := context.WithTimeout(context.Background(),(10 * time.Second))

源码分析:

// WithTimeout returns WithDeadline(parent,time.Now().Add(timeout)).//// Canceling this context releases resources associated with it,so code should// call cancel as soon as the operations running in this Context complete://// func slowOperationWithTimeout(ctx context.Context) (Result,error) {// ctx,cancel := context.WithTimeout(ctx,100*time.Millisecond)// defer cancel() // releases resources if slowOperation completes before timeout elapses// return slowOperation(ctx)// }func WithTimeout(parent Context,timeout time.Duration) (Context,CancelFunc) {    return WithDeadline(parent,time.Now().Add(timeout))}func WithDeadline(parent Context,deadline time.Time) (Context,CancelFunc) {    if cur,ok := parent.Deadline(); ok && cur.Before(deadline) {        // 被派生的context设置了超时且当前时间小于超时时间        // The current deadline is already sooner than the new one.        return WithCancel(parent)    }    c := &timerCtx{        cancelCtx: newCancelCtx(parent),deadline:  deadline,}    // check deadline passed    propagateCancel(parent,c)    d := time.Until(deadline)    if d <= 0 {        c.cancel(true,DeadlineExceeded) // deadline has already passed        return c,func() { c.cancel(true,Canceled) }    }    c.mu.Lock()    defer c.mu.Unlock()    if c.err == nil {        // timeout and cancel context        c.timer = time.AfterFunc(d,func() {            c.cancel(true,DeadlineExceeded)        })    }    return c,Canceled) }}func WithCancel(parent Context) (ctx Context,cancel CancelFunc) {    // 创建新的context    c := newCancelCtx(parent)    propagateCancel(parent,&c)    return &c,Canceled) }}func propagateCancel(parent Context,child canceler) {    if parent.Done() == nil {        return // parent is never canceled    }    // get partner cancel context    if p,ok := parentCancelCtx(parent); ok {        p.mu.Lock()        if p.err != nil {            // parent has already been canceled            child.cancel(false,p.err)        } else {            // build with map            if p.children == nil {                p.children = make(map[canceler]struct{})            }            p.children[child] = struct{}{}        }        p.mu.Unlock()    } else {        go func() {            select {            // if parent close,then child close()            case <-parent.Done():                child.cancel(false,parent.Err())            case <-child.Done():            }        }()    }}//判断parent是否为cancelCtx类型func parentCancelCtx(parent Context) (*cancelCtx,bool) {    for {        switch c := parent.(type) {        case *cancelCtx:            return c,true        case *timerCtx:            return &c.cancelCtx,true        case *valueCtx:            parent = c.Context        default:            return nil,false        }    }}

context 类型:
1. 可cancel的context:

// A cancelCtx can be canceled. When canceled,it also cancels any children// that implement canceler.type cancelCtx struct {    Context    done chan struct{} // closed by the first cancel call.    mu       sync.Mutex    children map[canceler]struct{} // set to nil by the first cancel call    err      error                 // set to non-nil by the first cancel call}// return channel !!!func (c *cancelCtx) Done() <-chan struct{} {    return c.done}func (c *cancelCtx) Err() error {    c.mu.Lock()    defer c.mu.Unlock()    return c.err}func (c *cancelCtx) String() string {    return fmt.Sprintf("%v.WithCancel",c.Context)}// cancel closes c.done,cancels each of c's children,and,if// removeFromParent is true,removes c from its parent's children.func (c *cancelCtx) cancel(removeFromParent bool,err error) {    if err == nil {        panic("context: internal error: missing cancel error")    }    c.mu.Lock()    if c.err != nil {        c.mu.Unlock()        return // already canceled    }    c.err = err    close(c.done)    for child := range c.children {        // NOTE: acquiring the child's lock while holding parent's lock.        child.cancel(false,err)    }    c.children = nil    c.mu.Unlock()    if removeFromParent {        removeChild(c.Context,c)    }}
带着计时的可cancel的context(匿名cancel的context)
// A timerCtx carrIEs a timer and a deadline. It embeds a cancelCtx to // implement Done and Err. It implements cancel by stopPing its timer then // delegating to cancelCtx.cancel.type timerCtx struct {    cancelCtx    timer *time.Timer // Under cancelCtx.mu.    deadline time.Time}func (c *timerCtx) Deadline() (deadline time.Time,ok bool) {    return c.deadline,true}func (c *timerCtx) String() string {    return fmt.Sprintf("%v.WithDeadline(%s [%s])",c.cancelCtx.Context,c.deadline,time.Until(c.deadline))}func (c *timerCtx) cancel(removeFromParent bool,err error) {    c.cancelCtx.cancel(false,err)    if removeFromParent {        // Remove this timerCtx from its parent cancelCtx's children.        removeChild(c.cancelCtx.Context,c)    }    c.mu.Lock()    if c.timer != nil {        c.timer.Stop()        c.timer = nil    }    c.mu.Unlock()}

key-value pair

// A valueCtx carrIEs a key-value pair. It implements Value for that key and// delegates all other calls to the embedded Context.type valueCtx struct {    Context    key,val interface{}}func (c *valueCtx) String() string {    return fmt.Sprintf("%v.WithValue(%#v,%#v)",c.Context,c.key,c.val)}func (c *valueCtx) Value(key interface{}) interface{} {    if c.key == key {        return c.val    }    return c.Context.Value(key)}
总结

以上是内存溢出为你收集整理的golang context 源码阅读全部内容,希望文章能够帮你解决golang context 源码阅读所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1274083.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存