Hone logo
Hone
Problems

Implementing Context.WithValue for Enhanced Request Handling

Context.WithValue in Go is a powerful tool for propagating request-specific data through function calls without explicitly passing it as arguments. This challenge asks you to implement a simplified version of context.WithValue to understand its underlying mechanics and how it facilitates cleaner, more maintainable code, particularly in scenarios like web request handling where you need to pass information like user IDs or request IDs across multiple middleware functions.

Problem Description

You are tasked with creating a WithValue function that mimics the core functionality of context.WithValue. This function should take a context and a key (of type interface{}) and a value (also of type interface{}) and return a new context with the key-value pair associated with it. The new context should be distinct from the original; modifying the value in the new context should not affect the original context. You also need to implement a Value function that retrieves the value associated with a given key from a context. If the key is not found, Value should return nil.

Key Requirements:

  • Immutability: The original context should remain unchanged. WithValue must return a new context.
  • Key-Value Association: The new context should store the provided key-value pair.
  • Value Retrieval: The Value function should correctly retrieve the value associated with a key.
  • Nil Handling: If a key is not found in the context, Value should return nil.
  • Type Safety (Limited): While the key and value are interface{}, the implementation should be designed to avoid unexpected type assertions or panics.

Expected Behavior:

  • Calling WithValue with a context, key, and value should return a new context containing the key-value pair.
  • Calling Value on the new context with the same key should return the provided value.
  • Calling Value on the original context (before WithValue was called) with the same key should return nil.
  • Calling Value on any context with a different key should return nil.

Edge Cases to Consider:

  • Nil context: Handle the case where the input context is nil gracefully (return a new context with the key-value pair).
  • Duplicate keys: The last value associated with a key should overwrite any previous values.
  • Type assertions: Be mindful of potential type assertion errors when retrieving values.

Examples

Example 1:

Input: context := context.Background(); key := "user_id"; value := 123
Output: newContext := WithValue(context, key, value); retrievedValue := Value(newContext, key)
Explanation: `WithValue` creates a new context. `Value` retrieves the value 123 from the new context.

Example 2:

Input: context := context.Background(); key := "request_id"; value := "abc-123"; newContext := WithValue(context, key, value); retrievedValue := Value(newContext, key)
Output: retrievedValue == "abc-123"
Explanation: Demonstrates the use of a string value.

Example 3: (Edge Case - Nil Context)

Input: context := nil; key := "some_key"; value := 42
Output: newContext := WithValue(context, key, value); retrievedValue := Value(newContext, key)
Explanation:  Handles the case where the initial context is nil.

Constraints

  • The WithValue function must not modify the original context.
  • The Value function must return nil if the key is not found.
  • The implementation should be reasonably efficient (avoid unnecessary allocations).
  • The key and value types are interface{}.
  • The solution should be concise and readable.

Notes

Consider using a map internally to store the key-value pairs associated with the context. Remember that contexts are often used in concurrent scenarios, so be mindful of potential race conditions if you were to extend this implementation further (though this is not a requirement for this challenge). Focus on the core functionality of associating and retrieving values. The goal is to understand the fundamental concept behind context.WithValue.

Loading editor...
go