// An emptyCtx is never canceled, has no values, and has no deadline. It is not // struct{}, since vars of this type must have distinct addresses. type emptyCtx int
func(*emptyCtx)Deadline()(deadline time.Time, ok bool) { return }
func(e *emptyCtx)String()string { switch e { case background: return"context.Background" case todo: return"context.TODO" } return"unknown empty Context" }
var ( background = new(emptyCtx) todo = new(emptyCtx) )
// Background returns a non-nil, empty Context. It is never canceled, has no // values, and has no deadline. It is typically used by the main function, // initialization, and tests, and as the top-level Context for incoming // requests. funcBackground()Context { return background }
// TODO returns a non-nil, empty Context. Code should use context.TODO when // it's unclear which Context to use or it is not yet available (because the // surrounding function has not yet been extended to accept a Context // parameter). funcTODO()Context { return todo }
// A cancelCtx can be canceled. When canceled, it also cancels any children // that implement canceler. type cancelCtx struct { Context
mu sync.Mutex // protects following fields done chanstruct{} // 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 }
func(c *cancelCtx)Done() <-chanstruct{} { c.mu.Lock() if c.done == nil { c.done = make(chanstruct{}) } d := c.done c.mu.Unlock() return d }
// 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 if c.done == nil { c.done = closedchan } else { 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) } }
1.5 valueCtx
通过 valueCtx 结构知道仅是在Context 的基础上增加了元素 key 和 value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 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{} }
funcmonitor(ctx context.Context, num int) { for { select { case <-ctx.Done(): fmt.Printf("Monitor[%d] stopped.\n", num) return default: value := ctx.Value("name") fmt.Printf("Monitor[%d] is running, value is %v\n", num, value) time.Sleep(2 * time.Second) } } }