// WithCancel returns a copy of parent with a new Done channel. The returned // context's Done channel is closed when the returned cancel function is called // or when the parent context's Done channel is closed, whichever happens first. // // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete.
// 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 done是一个channel,用来 传递关闭信号 children map[canceler]struct{} // set to nil by the first cancel call children是一个map,存储了当前context节点下的子节点 err error// set to non-nil by the first cancel call err用于存储错误信息 表示任务结束的原因 }
// A canceler is a context type that can be canceled directly. The // implementations are *cancelCtx and *timerCtx. type canceler interface { cancel(removeFromParent bool, err error) Done() <-chanstruct{} }
// Done is provided for use in select statements: // // // Stream generates values with DoSomething and sends them to out // // until DoSomething returns an error or ctx.Done is closed. // func Stream(ctx context.Context, out chan<- Value) error { // for { // v, err := DoSomething(ctx) // if err != nil { // return err // } // select { // case <-ctx.Done(): // return ctx.Err() // case out <- v: // } // } // } // // See https://blog.golang.org/pipelines for more examples of how to use // a Done channel for cancellation. Done() <-chanstruct{}
// If Done is not yet closed, Err returns nil. // If Done is closed, Err returns a non-nil error explaining why: // Canceled if the context was canceled // or DeadlineExceeded if the context's deadline passed. // After Err returns a non-nil error, successive calls to Err return the same error. Err() error
for { select { case res := <-ctx.Done(): fmt.Println("res:", res) return case res2 := <-cuiChan: fmt.Println("res2:", res2) default: fmt.Println("I am working!") time.Sleep(time.Second) } } }
for { select { case res := <-ctx.Done(): fmt.Println("res:", res) return case res2 := <-cuiChan: fmt.Println("res2:", res2) default: fmt.Println("I am working!") time.Sleep(time.Second) } } }