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
:
Go
package main
import (
"errors"
"fmt"
)
// checkNumber function checks if a number is positive or negative.
// If the number is negative, it returns an error.
func checkNumber(num int) (string, error) {
if num < 0 {
// Return an error when the number is negative
return "", errors.New("number is negative")
}
// Return a success message if the number is positive
return "number is positive", nil
}
func main() {
// Calling checkNumber with a negative value (-5)
result, err := checkNumber(-5)
if err != nil {
// If an error is returned, print the error message
fmt.Println("Error:", err) // Output: Error: number is negative
} else {
// If no error, print the success message
fmt.Println(result)
}
}
OutputError: 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:
Go
package main
import (
"errors"
"fmt"
)
func checkNumber(num int) (string, error) {
if num < 0 {
return "", errors.New("number is negative")
}
return "number is positive", nil
}
func main() {
result, err := checkNumber(-5)
if err != nil {
fmt.Println("Error:", err) // Output: Error: number is negative
} else {
fmt.Println(result)
}
}
OutputError: 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:
Go
import (
"errors"
"fmt"
)
// Declaring a custom error for invalid input
var ErrInvalidInput = errors.New("invalid input")
// Function to validate input and return an error if the input is empty
func validateInput(input string) error {
if input == "" {
// Wrapping the custom error using fmt.Errorf and %w for proper error chaining
return fmt.Errorf("validation error: %w", ErrInvalidInput)
}
return nil // No error if the input is valid
}
func main() {
// Calling validateInput with an empty string to simulate an error
err := validateInput("")
// Checking if the returned error matches the custom error using errors.Is()
if errors.Is(err, ErrInvalidInput) {
fmt.Println("Detected invalid input") // Prints message if error is of type ErrInvalidInput
}
}
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:
Go
package main
import (
"fmt"
)
// CustomError defines a custom error type with a code and message.
type CustomError struct {
Code int
Message string
}
// Error implements the error interface for CustomError.
func (e *CustomError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
// generateError creates and returns a new CustomError.
func generateError() error {
return &CustomError{Code: 404, Message: "Resource not found"}
}
func main() {
err := generateError()
fmt.Println(err) // Output: Error 404: Resource not found
}
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.
Similar Reads
Go Tutorial Go or you say Golang is a procedural and statically typed programming language having the syntax similar to C programming language. It was developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google but launched in 2009 as an open-source programming language and mainly used in Google
2 min read
Go Programming Language (Introduction) Go is a procedural programming language. It was developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google but launched in 2009 as an open-source programming language. Programs are assembled by using packages, for efficient management of dependencies. This language also supports env
11 min read
time.Sleep() Function in Golang With Examples In Go language, time packages supplies functionality for determining as well as viewing time. The Sleep() function in Go language is used to stop the latest go-routine for at least the stated duration d. And a negative or zero duration of sleep will cause this method to return instantly. Moreover, t
3 min read
Learn Free Programming Languages In this rapidly growing world, programming languages are also rapidly expanding, and it is very hard to determine the exact number of programming languages. Programming languages are an essential part of software development because they create a communication bridge between humans and computers. No
9 min read
Golang Tutorial - Learn Go Programming Language This Golang tutorial provides you with all the insights into Go Language programming, Here we provide the basics, from how to install Golang to advanced concepts of Go programming with stable examples. So, if you are a professional and a beginner, this free Golang tutorial is the best place for your
10 min read
strings.Contains Function in Golang with Examples strings.Contains Function in Golang is used to check the given letters present in the given string or not. If the letter is present in the given string, then it will return true, otherwise, return false. Syntax:Â func Contains(str, substr string) bool Here, str is the original string and substr is t
2 min read
Interfaces in Golang In Go, an interface is a type that lists methods without providing their code. You canât create an instance of an interface directly, but you can make a variable of the interface type to store any value that has the needed methods.Exampletype Shape interface { Area() float64 Perimeter() float64}In t
3 min read
Top 10 Golang Project Ideas with Source Code in 2025 Golang, or Go, a programming language was created by Google. It's widely used for building different kinds of applications like websites and cloud services. The fastest way to master this language is by building projects related to it. This article introduces 10 beginner-friendly to medium-difficult
8 min read
fmt.Sprintf() Function in Golang With Examples In Go language, fmt package implements formatted I/O with functions analogous to C's printf() and scanf() function. The fmt.Sprintf() function in Go language formats according to a format specifier and returns the resulting string. Moreover, this function is defined under the fmt package. Here, you
2 min read
Top 10 Golang Frameworks in 2025 Golang (or Go) is an open-source compiled programming language that is used to build simple, systematic, and secure software. It was designed by Google in the year 2007 and has been readily adopted by developers all over the world due to its features like memory safety, structural typing, garbage co
9 min read