WithTimeout vs WithDeadline: what is the difference, and what happens when a child asks for a later deadline than its parent?
Question 262MediumGo 1.22 to 1.25
WithTimeout(parent, d) is exactly WithDeadline(parent, time.Now().Add(d)). Use a timeout for a relative budget ("this call gets 2s") and a deadline when an absolute time is passed down from outside (for example a gRPC deadline or a job's SLA).
A child can never extend its parent's deadline. If the parent's deadline is already earlier, WithDeadline skips the timer and returns a plain WithCancel(parent). The child's Deadline() then reports the parent's earlier time.
parent, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
child, cancelChild := context.WithTimeout(parent, 10*time.Second)
defer cancelChild()
d, _ := child.Deadline()
fmt.Println(time.Until(d) <= 100*time.Millisecond) // true: the parent's deadline wins
Gotcha: if you really need work to outlive the parent's deadline (for example cleanup after a timed-out request), derive from context.WithoutCancel(parent) and set a new timeout. Deriving again from the original parent will not help.
More on Context
- Q260Explain how cancellation propagates through a context tree. What happens internally when a parent is canceled?
- Q261Why must you always call the CancelFunc, even if the operation finished successfully? What leaks if you don't?
- Q263What does this print?
- Q264What values can ctx.Err() return, and how should you check them?
- Q265What is WithCancelCause, and how does ctx.Err() differ from context.Cause(ctx)?
- Q266What does this print? (WithTimeoutCause and its cancel function)