This is a creation in Article, where the information may have evolved or changed.
GoA language context package can associate a set of functions that handle the same request with a goroutine context.Context variable of this type and provide a cancellation ( cancelation ) and timeout ( timeout ) mechanism. Personally, Sameer Ajmani this document: Cancelation, Context, and plumbing are written clearly and are easier to understand context package .
Update 1: The following Context definitions are selected from Go Concurrency patterns:context:
//A Context carries A deadline, cancelation signal, and request-scoped values//across API boundaries. Its methods is safe for simultaneous use by multiple//Goroutines.type Context Interface {//Done returns a channel T Hat is closed if this Context is a canceled//or times out. Done () <-chan struct{}//ERR indicates why this context was canceled, after the Do channel//is closed. ERR () error//Deadline returns the time when this Context would be is canceled, if any. Deadline () (Deadline time. Time, OK bool)//value returns the value associated with key or nil if none. Value (Key interface{}) interface{}}
The four functions are defined as follows:
A) The Done function returns a read channel -only, so only for its operation close . And this channel will only be in the Context cancel timeout case of being or close ;
b) Err is Done channel close after being used to obtain close the reason and returns a non-nil value of: context canceled or context deadline exceeded ;
c) Deadline returns Context cancel the time that was taken. If it is ok false , it indicates that there is no setting deadline ;
D) Value returns the same key bound value, if no corresponding value is returned nil .
Update 2: Simply analyze the source code:
// 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 intfunc (*emptyCtx) Deadline() (deadline time.Time, ok bool) { return}func (*emptyCtx) Done() <-chan struct{} { return nil}func (*emptyCtx) Err() error { return nil}func (*emptyCtx) Value(key interface{}) interface{} { return nil}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))
context.Background()And context.TODO() What is returned is actually a emptyCtx pointer to the type variable.
Look again at the WithCancel() function implementation:
// 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.func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, c) return c, func() { c.cancel(true, Canceled) }}// newCancelCtx returns an initialized cancelCtx.func newCancelCtx(parent Context) *cancelCtx { return &cancelCtx{ Context: parent, done: make(chan struct{}), }}
And the cancelCtx definition is as follows:
// 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]bool // set to nil by the first cancel call err error // set to non-nil by the first cancel call}
Each time the function is called WithCancel , the newly generated Context will contain " 父Context " and a new one done channel .
propagateCancel()The function is implemented as follows:
// propagateCancel arranges for child to be canceled when parent is.func propagateCancel(parent Context, child canceler) { if parent.Done() == nil { return // parent is never canceled } if p, ok := parentCancelCtx(parent); ok { p.mu.Lock() if p.err != nil { // parent has already been canceled child.cancel(false, p.err) } else { if p.children == nil { p.children = make(map[canceler]bool) } p.children[child] = true } p.mu.Unlock() } else { go func() { select { case <-parent.Done(): child.cancel(false, parent.Err()) case <-child.Done(): } }() }}
This function is the addition of the newly generated Context 父Context children members, so as to form a "cascade" cancel operation.
Other References:
Package context,
Concurrent patterns in Golang:context;
context and cancellation of Goroutines.