In a complex system, or even in a small one, when a context.Context
is cancelled, we need a way to know what caused the cancellation. It is possible that context.Context
was cancelled by a context.CancelFunc
successfully, if it was cancelled because it timed out, or some other reason.
The context.Context.Err
method, Listing 12.1 returns the error that caused the context to be cancelled.
$ go doc context.Context.Err
package context // import "context"
type Context interface {
// 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
}
--------------------------------------------------------------------------------
Go Version: go1.23.0
Listing 12.1: The context.Context.Err
method.
Context Cancelled Error
The context
package defines two different error
variables that can be used to check an error
that was returned from context.Context.Err
method.
The first is context.Canceled
, Listing 12.2 , which is returned when the context is cancelled through the use of a context.CancelFunc
function. This error
is considered to indicate a "successful" cancellation.
$ go doc context.Canceled
package context // import "context"
var Canceled = errors.New("context canceled")
Canceled is the error returned by [Context.Err] when the context is
canceled.
--------------------------------------------------------------------------------
Go Version: go1.23.0
Listing 12.2: The context.Canceled
error
.
Consider Listing 12.3 . When we first check the context.Context.Err
method, it returns nil
. After we call the context.CancelFunc
function provided by context.WithCancel
, the context.Context.Err
method returns a context.Canceled
error.
func main() {
// create a background context
ctx := context.Background()
// wrap the context with a
// cancellable context
ctx, cancel := context.WithCancel(ctx)
// check the error:
//
fmt.Println("ctx.Err()", ctx.Err())
// cancel the context
cancel()
// check the error:
// context.Canceled
fmt.Println("ctx.Err()", ctx.Err())
// check the error again:
// context.Canceled
fmt.Println("ctx.Err()", ctx.Err())
}
$ go run .
ctx.Err() <nil>
ctx.Err() context canceled
ctx.Err() context canceled
--------------------------------------------------------------------------------
Go Version: go1.23.0
Listing 12.3: Checking for cancellation errors.
As we can see from the output in Listing 12.3 , repeated calls to the context.Context.Err
method return the same context.Canceled
error.
Context Deadline Exceeded Error
When a context.Context
is cancelled due to a deadline, or timeout, being exceeded, the context.Context.Err
method returns a context.DeadlineExceeded
error, Listing 12.4 .
$ go doc context.DeadlineExceeded
package context // import "context"
var DeadlineExceeded error = deadlineExceededError{}
DeadlineExceeded is the error returned by [Context.Err] when the context's
deadline passes.
--------------------------------------------------------------------------------
Go Version: go1.23.0
Listing 12.4: The context.DeadlineExceeded
error
.
Consider Listing 12.5 . We create a context.Context
that will self cancel after 1 second. When we check context.Context.Err
method, before the context.Context
times out, it returns nil
.
func main() {
// create a background context
ctx := context.Background()
// wrap the context that will
// self cancel after 10 milliseconds
ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond)
defer cancel()
// check the error:
//
fmt.Println("ctx.Err()", ctx.Err())
// wait for the context to self cancel
<-ctx.Done()
// check the error:
// context.Canceled
fmt.Println("ctx.Err()", ctx.Err())
// check the error again:
// context.DeadlineExceeded
fmt.Println("ctx.Err()", ctx.Err())
}
$ go run .
ctx.Err() <nil>
ctx.Err() context deadline exceeded
ctx.Err() context deadline exceeded
--------------------------------------------------------------------------------
Go Version: go1.23.0
Listing 12.5: Checking for deadline exceeded errors.
As we can see from the output, the context.Context
times out after the specified time, and the context.Context.Err
method returns a context.DeadlineExceeded
error.