Hone logo
Hone
Problems

Advanced Error Handling: Implementing Error Wrapping in Go

Understanding and effectively managing errors is crucial for building robust Go applications. Error wrapping, a feature introduced in Go 1.13, allows you to chain errors, providing richer context about the origin and nature of a failure without losing the original error information. This challenge will test your ability to implement and utilize error wrapping.

Problem Description

Your task is to design and implement a system that simulates a multi-layered operation, where each layer can return an error. You will need to wrap these underlying errors with custom error types to add specific context at each level. The final error returned by the top-level operation should contain the complete chain of contextual information.

Key Requirements:

  1. Define Custom Error Types: Create at least three distinct custom error types. Each type should represent a specific layer or stage in the simulated operation (e.g., NetworkError, DatabaseError, ProcessingError).
  2. Implement Error() Method: Each custom error type must implement the error interface by providing an Error() method that returns a descriptive string.
  3. Implement Error Wrapping: For each custom error type, implement the Unwrap() method. This method should return the underlying error that caused the current error. If there is no underlying error, Unwrap() should return nil.
  4. Simulate Multi-Layered Operation: Create a set of functions that mimic a sequence of operations. Each function can potentially return an error from a lower layer.
  5. Error Inspection: Write a function that takes the final error from the simulated operation and uses errors.Is() and errors.As() (from the errors package) to inspect the error chain and identify specific types of errors or their presence.

Expected Behavior:

When an error occurs in a lower layer, the calling function should wrap that error with its own contextual error type before returning it. The top-level function should return the final wrapped error. The error inspection function should be able to accurately detect specific wrapped errors within the chain.

Edge Cases to Consider:

  • A function that successfully completes without returning an error.
  • An error that occurs at the very first layer.
  • An error that occurs at the deepest layer.

Examples

Example 1:

Input: simulate a successful operation
Output: nil
Explanation: The simulated operation completes without any errors.

Example 2:

Input: simulate an operation where a database error occurs during processing
Output: operation failed: processing error: failed to query database: connection refused
Explanation:
- The deepest error is "connection refused".
- This is wrapped by a "DatabaseError" with the message "failed to query database".
- This is then wrapped by a "ProcessingError" with the message "processing error".
- Finally, the top-level operation wraps it with "operation failed".

Example 3:

Input: simulate an operation where a network error occurs, which is then wrapped by a database error, and then a processing error.
Output: operation failed: processing error: database operation failed: network issue: timeout
Explanation:
- The root error is "timeout" (simulated network issue).
- This is wrapped by a "DatabaseError" with the message "network issue".
- This is then wrapped by a "ProcessingError" with the message "database operation failed".
- The top-level operation wraps it with "operation failed".

Constraints

  • Your solution should be written in Go.
  • You must use the standard errors package, specifically errors.Is() and errors.As().
  • The code should be well-commented, explaining the purpose of custom error types and the wrapping logic.
  • No external libraries are allowed for error handling.

Notes

  • Familiarize yourself with the errors.Is() and errors.As() functions in Go.
  • Think about how to define your custom error types to hold relevant contextual information.
  • Consider the order in which errors are wrapped – it should reflect the call stack or data flow.
  • The Unwrap() method is the key to enabling the errors package functions to traverse the error chain.
Loading editor...
go