func WithTimeout
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
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) }
Not only is WithTimeout
conceptually similar to WithDeadline
, it literally is WithDeadline
, as we can see form the source code:
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
Despite the technical near-duplication, you’ll probably use context.WithTimeout
far more frequently than context.WithDeadline
. It’s the most universal and idiomatic way to handle all kinds of timeouts:
func fetchUser(ctx context.Context, userID int) (*User, error) {
ctx, cancel = context.WithTimeout(ctx, 500 * time.Millisecond)
defer cancel()
user, err := db.FetchUser(ctx, userID)
if err != nil {
return nil, err
}
/* ... other logic ... */
return user, nil
}
Various Go packages have other ways to set timeouts. Many of these are legacy—often added before Go 1.7 added the context
package—and have therefore been deprecated in favor of the approach shown above. One example can be found in the net/http.Client’s Timeout
field:
// Timeout specifies a time limit for requests made by this // Client. The timeout includes connection time, any // redirects, and reading the response body. The timer remains // running after Get, Head, Post, or Do return and will // interrupt reading of the Response.Body. // // A Timeout of zero means no timeout. // // The Client cancels requests to the underlying Transport // as if the Request's Context ended. // // For compatibility, the Client will also use the deprecated // CancelRequest method on Transport if found. New // RoundTripper implementations should use the Request's Context // for cancellation instead of implementing CancelRequest. Timeout time.Duration
And, of course, there’s the with-cause variation as well:
func WithTimeoutCause
func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)
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.