// cancel closes c.done, cancels each of c's children, and, if // removeFromParent is true, removes c from its parent's children. // cancel sets c.cause to cause if this is the first time c is canceled. func(c *cancelCtx) cancel(removeFromParent bool, err, cause error) { if err == nil { panic("context: internal error: missing cancel error") } if cause == nil { cause = err } c.mu.Lock() if c.err != nil { c.mu.Unlock() return// already canceled // 已经被其他协程取消 } c.err = err c.cause = cause d, _ := c.done.Load().(chanstruct{}) if d == nil { c.done.Store(closedchan) } else { close(d) } // 遍历它的所有子节点 for child := range c.children { // 递归地取消所有子节点 child.cancel(false, err, cause) } // 将子节点置空 c.children = nil c.mu.Unlock()
if removeFromParent { // 从父节点中移除自己 removeChild(c.Context, c) } }
// removeChild removes a context from its parent. funcremoveChild(parent Context, child canceler) { if s, ok := parent.(stopCtx); ok { s.stop() return } p, ok := parentCancelCtx(parent) if !ok { return } p.mu.Lock() if p.children != nil { delete(p.children, child) } p.mu.Unlock() }
funcwithCancel(parent Context) *cancelCtx { if parent == nil { panic("cannot create context from nil parent") } c := &cancelCtx{} c.propagateCancel(parent, c) return c }
// 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 any }
func(c *valueCtx) Value(key any) any { if c.key == key { return c.val } return value(c.Context, key) }
funcvalue(c Context, key any) any { for { switch ctx := c.(type) { case *valueCtx: if key == ctx.key { return ctx.val } c = ctx.Context case *cancelCtx: if key == &cancelCtxKey { return c } c = ctx.Context case withoutCancelCtx: if key == &cancelCtxKey { // This implements Cause(ctx) == nil // when ctx is created using WithoutCancel. returnnil } c = ctx.c case *timerCtx: if key == &cancelCtxKey { return &ctx.cancelCtx } c = ctx.Context case backgroundCtx, todoCtx: returnnil default: return c.Value(key) } } }