VOOZH about

URL: https://www.geeksforgeeks.org/go-language/go-error-handling/

⇱ Go Error Handling - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Go Error Handling

Last Updated : 4 Feb, 2025

In Go, error handling is done by returning error values instead of using try-catch like in Java or Python. This approach ensures explicit error handling, improving code clarity and control.

The error type in Go is an interface with a single method:

type error interface {
Error() string
}

Any type implementing this method is treated as an error, keeping error handling simple and avoiding complex exception hierarchies.

Creating and Returning Errors in Go

1. Using errors.New

Go provides a simple errors package for creating basic error messages. Here's how you can create and return an error using errors.New:


Output
Error: number is negative

Explanation:

  • The checkNumber function returns an error if the number is negative.
  • If no error occurs, the function returns a success message along with a nil error.

2. Returning nil for No Error

When no error occurs, it's common to return nil as the error value. This is the default "zero" value for errors in Go:

return "operation successful", nil

Wrapping Errors for Better Traceability

For more complex error handling, Go provides fmt.Errorf to wrap errors with additional context. This feature is incredibly useful for tracing the source of errors and understanding their context as they bubble up through function calls.

Example:


Output
Error: number is negative

The %w verb in fmt.Errorf can wrap an error to preserve its context for further investigation:

err := fmt.Errorf("failed operation: %w", errors.New("network timeout"))
originalErr := errors.Unwrap(err)
fmt.Println(originalErr) // Output: network timeout

Unwrapping Errors

In Go 1.13 and later, the errors package provides the Unwrap function to extract the original error from a wrapped error. This is particularly useful when multiple layers of errors are involved.

Example:

err := fmt.Errorf("failed operation: %w", errors.New("network timeout"))
originalErr := errors.Unwrap(err)
fmt.Println(originalErr) // Output: network timeout

Comparing Errors with errors.Is

Go provides the errors.Is function to compare errors, including errors that have been wrapped. This allows you to check if an error matches a specific predefined error, even if it has been wrapped multiple times.

Example:

Explanation:

  • We define a sentinel error ErrInvalidInput.
  • errors.Is checks whether the error returned from validateInput matches the sentinel error, even if it's wrapped in additional context.

Using Custom Errors

While Go’s built-in error handling works for many scenarios, sometimes you need more specific error types. Custom error types can carry additional data and provide more context about the error.

Example:

Explanation:

  • We define a CustomError struct with additional fields for Code and Message.
  • The Error method implements the error interface, allowing it to be used as an error.

Key Error Handling Functions in Go

  • errors.New: Creates a basic error with a message.
  • fmt.Errorf: Wraps an error with additional context, using %w to preserve the original error.
  • errors.Unwrap: Extracts the original error from a wrapped error.
  • errors.Is: Checks if an error matches a predefined error.
  • errors.As: Extracts a specific error type from an error chain.

Best Practices for Error Handling in Go

  • Use Specifications: Define common request and response properties in one place to avoid repetition.
  • Modularize Code: Create reusable methods for commonly used operations, such as creating test data or making common API calls.
  • Validate Response Details: Always verify status codes, response bodies, and headers to ensure correct API behavior.
  • Handle Dynamic Data: Use response data from one API call in subsequent requests to test end-to-end workflows.
  • Incorporate Logging: Enable logs for debugging and detailed visibility during failures.

Conclusion

Go’s error handling is simple and explicit, treating errors as values for better code predictability. You can create errors using errors.New, wrap them with fmt.Errorf, or define custom error types. By following best practices, you can write robust, maintainable, and bug-free code, ensuring smooth development and production performance.

Comment
Article Tags:
Article Tags:

Explore