Canceling in-progress operations
You can manage in-progress operations by using Go
context.Context. A Context is a
standard Go data value that can report whether the overall operation it
represents has been canceled and is no longer needed. By passing a
context.Context across function calls and services in your application, those
can stop working early and return an error when their processing is no longer
needed. For more about Context, see
Go Concurrency Patterns: Context.
For example, you might want to:
- End long-running operations, including database operations that are taking too long to complete.
- Propagate cancellation requests from elsewhere, such as when a client closes a connection.
Many APIs for Go developers include methods that take a Context argument,
making it easier for you to use Context throughout your application.
Canceling database operations after a timeout
You can use a Context to set a timeout or deadline after which an operation
will be canceled. To derive a Context with a timeout or deadline, call
context.WithTimeout or
context.WithDeadline.
Code in the following timeout example derives a Context and passes it into
the sql.DB QueryContext
method.
func QueryWithTimeout(ctx context.Context) {
// Create a Context with a timeout.
queryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// Pass the timeout Context with a query.
rows, err := db.QueryContext(queryCtx, "SELECT * FROM album")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Handle returned rows.
}
When one context is derived from an outer context, as queryCtx is derived
from ctx in this example, if the outer context is canceled, then the derived
context is automatically canceled as well. For example, in HTTP servers, the
http.Request.Context method returns a context associated with the request.
That context is canceled if the HTTP client disconnects or cancels the HTTP
request (possible in HTTP/2). Passing an HTTP request’s context to
QueryWithTimeout above would cause the database query to stop early either
if the overall HTTP request was canceled or if the query took more than five
seconds.
Note: Always defer a call to the cancel function that’s returned when you
create a new Context with a timeout or deadline. This releases resources held
by the new Context when the containing function exits. It also cancels
queryCtx, but by the time the function returns, nothing should be using
queryCtx anymore.