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 源码阅读所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)