Today we’re talking about canceling contexts based on time. Arguably, this should have come first, as it’s a little simpler to work with than the explicit cancelation we talked about a week ago. But once again, I’m going in essentially alphabetical order, so it’s what we have…
func WithDeadline
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
WithDeadline returns a derived context that points to the parent context but has 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.
So here we have the ability to cancel a context at a fixed point in the future.
func cinderella(ctx context.Context) error {
midnight := time.Now().Add(24 * time.Hour).Truncate(24 * time.Hour)
ctx, cancel := context.WithDeadline(ctx, midnight)
defer cancel()
carriage := pumpkin.Transform()
go toTheBall(ctx)
<-ctx.Done() // Wait for context cancellation
return carriage.Close()
}
What if we have multiple possible deadlines in play on the same context, and want to differentiate between them?
Then you can use the related WithDeadlineCause
function:
func WithDeadlineCause
func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc)
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.
This works similarly to the WithCancelCause
function recently discussed, but rather than the cancel function accepting the cause, you set the cause at the same time you set the deadline.
ctx, cancel := context.WithDeadlineCause(ctx, midnight, errors.New("magic spell expired"))