Implementing Context with Timeout in Go
Contexts are fundamental in Go for managing request-scoped values, cancellation signals, and deadlines. This challenge focuses on implementing a function that leverages context.WithTimeout to create a context with a specified timeout duration. This is crucial for building robust and responsive applications that gracefully handle long-running operations and prevent resource exhaustion.
Problem Description
You are tasked with creating a Go function named WithTimeoutContext that takes a parent context and a timeout duration as input. The function should return a new context derived from the parent context, but with a timeout applied. If the timeout expires before any operations using the new context are completed, the context should be canceled. The function should also return the cancel function associated with the new context, allowing the caller to explicitly cancel the context if needed (though this isn't strictly required for the core functionality).
Key Requirements:
- The function must accept a
context.Contextand atime.Durationas input. - It must use
context.WithTimeoutto create a new context with the specified timeout. - The function must return the new context and the associated
cancelfunction. - The returned context should be derived from the parent context, inheriting its values and cancellation signals.
Expected Behavior:
When the timeout duration elapses, the returned context should be automatically canceled. Any operations using this context should receive a context.Canceled error. If the parent context is canceled before the timeout expires, the new context should also be canceled immediately.
Edge Cases to Consider:
- What happens if the timeout duration is zero?
- What happens if the parent context is already canceled?
- How does the function handle potential errors during context creation (though
context.WithTimeoutrarely errors)?
Examples
Example 1:
Input: parentContext := context.Background(); timeout := 2 * time.Second
Output: newContext, cancel := WithTimeoutContext(parentContext, timeout)
Explanation: A new context is created derived from `context.Background()` with a timeout of 2 seconds. If no operations are performed on `newContext` within 2 seconds, it will be canceled.
Example 2:
Input: parentContext := context.Background(); timeout := 0 * time.Second
Output: newContext, cancel := WithTimeoutContext(parentContext, timeout)
Explanation: A new context is created derived from `context.Background()` with a timeout of 0 seconds. The context will be immediately canceled.
Example 3:
Input: parentContext := context.Canceled(); timeout := 1 * time.Second
Output: newContext, cancel := WithTimeoutContext(parentContext, timeout)
Explanation: Since the parent context is already canceled, the new context will also be immediately canceled, regardless of the timeout duration.
Constraints
- The timeout duration must be a non-negative
time.Duration. - The parent context must be a valid
context.Context. - The function should be efficient and avoid unnecessary allocations.
- The function should not panic under any circumstances.
Notes
- Consider using
defer cancel()within the function to ensure the cancel function is always called, even if an error occurs. - The
cancelfunction is provided for more granular control over context cancellation, but the core requirement is to create a context with a timeout. - Think about how the parent context's cancellation signals are propagated to the new context.