Involved Source Files Package context defines the Context type, which carries deadlines,
cancellation signals, and other request-scoped values across API boundaries
and between processes.
Incoming requests to a server should create a [Context], and outgoing
calls to servers should accept a Context. The chain of function
calls between them must propagate the Context, optionally replacing
it with a derived Context created using [WithCancel], [WithDeadline],
[WithTimeout], or [WithValue]. When a Context is canceled, all
Contexts derived from it are also canceled.
The [WithCancel], [WithDeadline], and [WithTimeout] functions take a
Context (the parent) and return a derived Context (the child) and a
[CancelFunc]. Calling the CancelFunc cancels the child and its
children, removes the parent's reference to the child, and stops
any associated timers. Failing to call the CancelFunc leaks the
child and its children until the parent is canceled or the timer
fires. The go vet tool checks that CancelFuncs are used on all
control-flow paths.
The [WithCancelCause] function returns a [CancelCauseFunc], which
takes an error and records it as the cancellation cause. Calling
[Cause] on the canceled context or any of its children retrieves
the cause. If no cause is specified, Cause(ctx) returns the same
value as ctx.Err().
Programs that use Contexts should follow these rules to keep interfaces
consistent across packages and enable static analysis tools to check context
propagation:
Do not store Contexts inside a struct type; instead, pass a Context
explicitly to each function that needs it. The Context should be the first
parameter, typically named ctx:
func DoSomething(ctx context.Context, arg Arg) error {
// ... use ctx ...
}
Do not pass a nil [Context], even if a function permits it. Pass [context.TODO]
if you are unsure about which Context to use.
Use context Values only for request-scoped data that transits processes and
APIs, not for passing optional parameters to functions.
The same Context may be passed to functions running in different goroutines;
Contexts are safe for simultaneous use by multiple goroutines.
See https://blog.golang.org/context for example code for a server that uses
Contexts.
Code Examples
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
waitOnCond := func(ctx context.Context, cond *sync.Cond, conditionMet func() bool) error {
stopf := context.AfterFunc(ctx, func() {
// We need to acquire cond.L here to be sure that the Broadcast
// below won't occur before the call to Wait, which would result
// in a missed signal (and deadlock).
cond.L.Lock()
defer cond.L.Unlock()
// If multiple goroutines are waiting on cond simultaneously,
// we need to make sure we wake up exactly this one.
// That means that we need to Broadcast to all of the goroutines,
// which will wake them all up.
//
// If there are N concurrent calls to waitOnCond, each of the goroutines
// will spuriously wake up O(N) other goroutines that aren't ready yet,
// so this will cause the overall CPU cost to be O(N²).
cond.Broadcast()
})
defer stopf()
// Since the wakeups are using Broadcast instead of Signal, this call to
// Wait may unblock due to some other goroutine's context becoming done,
// so to be sure that ctx is actually done we need to check it in a loop.
for !conditionMet() {
cond.Wait()
if ctx.Err() != nil {
return ctx.Err()
}
}
return nil
}
cond := sync.NewCond(new(sync.Mutex))
var wg sync.WaitGroup
for i := 0; i < 4; i++ {
wg.Add(1)
go func() {
defer wg.Done()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()
cond.L.Lock()
defer cond.L.Unlock()
err := waitOnCond(ctx, cond, func() bool { return false })
fmt.Println(err)
}()
}
wg.Wait()
}
package main
import (
"context"
"fmt"
"net"
"time"
)
func main() {
readFromConn := func(ctx context.Context, conn net.Conn, b []byte) (n int, err error) {
stopc := make(chan struct{})
stop := context.AfterFunc(ctx, func() {
conn.SetReadDeadline(time.Now())
close(stopc)
})
n, err = conn.Read(b)
if !stop() {
// The AfterFunc was started.
// Wait for it to complete, and reset the Conn's deadline.
<-stopc
conn.SetReadDeadline(time.Time{})
return n, ctx.Err()
}
return n, err
}
listener, err := net.Listen("tcp", ":0")
if err != nil {
fmt.Println(err)
return
}
defer listener.Close()
conn, err := net.Dial(listener.Addr().Network(), listener.Addr().String())
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()
b := make([]byte, 1024)
_, err = readFromConn(ctx, conn, b)
fmt.Println(err)
}
package main
import (
"context"
"errors"
"fmt"
)
func main() {
// mergeCancel returns a context that contains the values of ctx,
// and which is canceled when either ctx or cancelCtx is canceled.
mergeCancel := func(ctx, cancelCtx context.Context) (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancelCause(ctx)
stop := context.AfterFunc(cancelCtx, func() {
cancel(context.Cause(cancelCtx))
})
return ctx, func() {
stop()
cancel(context.Canceled)
}
}
ctx1, cancel1 := context.WithCancelCause(context.Background())
defer cancel1(errors.New("ctx1 canceled"))
ctx2, cancel2 := context.WithCancelCause(context.Background())
mergedCtx, mergedCancel := mergeCancel(ctx1, ctx2)
defer mergedCancel()
cancel2(errors.New("ctx2 canceled"))
<-mergedCtx.Done()
fmt.Println(context.Cause(mergedCtx))
}
package main
import (
"context"
"fmt"
)
func main() {
// gen generates integers in a separate goroutine and
// sends them to the returned channel.
// The callers of gen need to cancel the context once
// they are done consuming generated integers not to leak
// the internal goroutine started by gen.
gen := func(ctx context.Context) <-chan int {
dst := make(chan int)
n := 1
go func() {
for {
select {
case <-ctx.Done():
return // returning not to leak the goroutine
case dst <- n:
n++
}
}
}()
return dst
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
}
{
d := time.Now().Add(shortDuration)
ctx, cancel := context.WithDeadline(context.Background(), d)
defer cancel()
select {
case <-neverReady:
fmt.Println("ready")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
{
ctx, cancel := context.WithTimeout(context.Background(), shortDuration)
defer cancel()
select {
case <-neverReady:
fmt.Println("ready")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
package main
import (
"context"
"fmt"
)
func main() {
type favContextKey string
f := func(ctx context.Context, k favContextKey) {
if v := ctx.Value(k); v != nil {
fmt.Println("found value:", v)
return
}
fmt.Println("key not found:", k)
}
k := favContextKey("language")
ctx := context.WithValue(context.Background(), k, "Go")
f(ctx, k)
f(ctx, favContextKey("color"))
}
Package-Level Type Names (total 3)
/* sort by: | */
A CancelCauseFunc behaves like a [CancelFunc] but additionally sets the cancellation cause.
This cause can be retrieved by calling [Cause] on the canceled Context or on
any of its derived Contexts.
If the context has already been canceled, CancelCauseFunc does not set the cause.
For example, if childContext is derived from parentContext:
- if parentContext is canceled with cause1 before childContext is canceled with cause2,
then Cause(parentContext) == Cause(childContext) == cause1
- if childContext is canceled with cause2 before parentContext is canceled with cause1,
then Cause(parentContext) == cause1 and Cause(childContext) == cause2
func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc)
AfterFunc arranges to call f in its own goroutine after ctx is done
(canceled or timed out).
If ctx is already done, AfterFunc calls f immediately in its own goroutine.
Multiple calls to AfterFunc on a context operate independently;
one does not replace another.
Calling the returned stop function stops the association of ctx with f.
It returns true if the call stopped f from being run.
If stop returns false,
either the context is done and f has been started in its own goroutine;
or f was already stopped.
The stop function does not wait for f to complete before returning.
If the caller needs to know whether f is completed,
it must coordinate with f explicitly.
If ctx has a "AfterFunc(func()) func() bool" method,
AfterFunc will use it to schedule the call.
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.
Cause returns a non-nil error explaining why c was canceled.
The first cancellation of c or one of its parents sets the cause.
If that cancellation happened via a call to CancelCauseFunc(err),
then [Cause] returns err.
Otherwise Cause(c) returns the same value as c.Err().
Cause returns nil if c has not been canceled yet.
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).
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.
WithCancelCause behaves like [WithCancel] but returns a [CancelCauseFunc] instead of a [CancelFunc].
Calling cancel with a non-nil error (the "cause") records that error in ctx;
it can then be retrieved using Cause(ctx).
Calling cancel with nil sets the cause to Canceled.
Example use:
ctx, cancel := context.WithCancelCause(parent)
cancel(myError)
ctx.Err() // returns context.Canceled
context.Cause(ctx) // returns myError
WithDeadline returns a copy of the parent context with the deadline adjusted
to be no later than d. If the parent's deadline is already earlier than d,
WithDeadline(parent, d) is semantically equivalent to parent. The returned
[Context.Done] channel is closed when the deadline expires, 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.
WithDeadlineCause behaves like [WithDeadline] but also sets the cause of the
returned Context when the deadline is exceeded. The returned [CancelFunc] does
not set the cause.
WithoutCancel returns a copy of parent that is not canceled when parent is canceled.
The returned context returns no Deadline or Err, and its Done channel is nil.
Calling [Cause] on the returned context returns nil.
WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
Canceling this context releases resources associated with it, so code should
call cancel as soon as the operations running in this [Context] complete:
func slowOperationWithTimeout(ctx context.Context) (Result, error) {
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer cancel() // releases resources if slowOperation completes before timeout elapses
return slowOperation(ctx)
}
WithTimeoutCause behaves like [WithTimeout] but also sets the cause of the
returned Context when the timeout expires. The returned [CancelFunc] does
not set the cause.
WithValue returns a copy of parent in which the value associated with key is
val.
Use context Values only for request-scoped data that transits processes and
APIs, not for passing optional parameters to functions.
The provided key must be comparable and should not be of type
string or any other built-in type to avoid collisions between
packages using context. Users of WithValue should define their own
types for keys. To avoid allocating when assigning to an
interface{}, context keys often have concrete type
struct{}. Alternatively, exported context key variables' static
type should be a pointer or interface.
Package-Level Variables (total 2)
Canceled is the error returned by [Context.Err] when the context is canceled.
DeadlineExceeded is the error returned by [Context.Err] when the context's
deadline passes.
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.