type cancelCtx struct { Context mu sync.Mutex // 互斥锁保护下面几个字段 done chan struct{} // 没有初始化, 第一个cancel调用会关闭这个管道 children map[canceler]struct{} // 第一个cancel调用会将其设置为nil err error // 第一个cancel调用会将其设置为非nil } // 返回done func (c *cancelCtx) Done() <-chan struct{} { c.mu.Lock() if c.done == nil { c.done = make(chan struct{}) } d := c.done c.mu.Unlock() return d } // 返回err func (c *cancelCtx) Err() error { c.mu.Lock() defer c.mu.Unlock() return c.err } var closedchan = make(chan struct{}) func init() { close(closedchan) } // 接收一个bool值和一个err值 // 第一次调用,将err值赋值给c.err,同时如果c.done未初始化,就直接赋一个已经关闭的管道给它;初始化了,就关闭 // 对于c.children,都进行取消,最终将c.children设置为nil // 如果第一个参数removeFromParent是true,那么从父Context中将当前的cancelCtx去掉 // 第二次调用的话,检查到err已经被赋值,就直接返回。 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) } }