blob: d01efc7acefab6c68073b70a230969bd7fc00908 [file] [log] [blame] [view]
<!--{
"Title": "Canceling in-progress operations"
}-->
You can manage in-progress operations by using Go
[`context.Context`](https://pkg.go.dev/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](https://blog.golang.org/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 {#timeout_cancel}
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`](https://pkg.go.dev/context#WithTimeout) or
[`context.WithDeadline`](https://pkg.go.dev/context#WithDeadline).
Code in the following timeout example derives a `Context` and passes it into
the `sql.DB` [`QueryContext`](https://pkg.go.dev/database/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.