Go Essentials

Go Essentials

Go Essentials

Error Handling in Go

Error Handling in Go

Error handling is a critical aspect of software engineering, as it helps ensure the reliability and stability of your applications. Go promotes a simple yet effective error-handling approach, making identifying and handling errors consistently easier. Let's explore error handling in Go:

Error Type

In Go, errors are represented by the built-in error type, which is an interface that includes a single method:

type error interface {
    Error() string
}

To create an error, you can use the errors.New function, which returns an error with the given error message:

package main

import (
    "errors"
    "fmt"
)

func divide(x, y int) (int, error) {
    if y == 0 {
        return 0, errors.New("division by zero")
    }
    return x / y, nil
}

func main() {
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err) // Output: Error: division by zero
    } else {
        fmt.Println("Result:", result) // Output: Result: 5
    }
}

Custom Errors

You can also create custom error types by implementing the error interface for a struct.

package main

import "fmt"

type CustomError struct {
    message string
}

func (ce CustomError) Error() string {
    return ce.message
}

func process() error {
    return CustomError{message: "custom error occurred"}
}

func main() {
    err := process()
    if err != nil {
        fmt.Println("Error:", err) // Output: Error: custom error occurred
    }
}

Error Wrapping

Go 1.13 introduced the errors.Wrap function from the "errors" package allows you to add context to errors, making them more informative.


import (
    "fmt"
    "github.com/pkg/errors"
)

func process() error {
    return errors.Wrap(cause(), "error occurred while processing data")
}

func cause() error {
    return errors.New("root cause error")
}

func main() {
    err := process()
    if err != nil {
        fmt.Println("Error:", err) // Output: Error: error occurred while processing data: root cause error
    }
}

Using errors.Wrap, you can wrap an error with additional context at different application levels, providing more useful information for debugging and understanding the error's origin.

Error Handling with Multiple Returns

In Go, it is common to use multiple return values, where the last value is typically an error. This approach allows you to handle both the result and the error simultaneously.

package main

import (
    "fmt"
    "os"
)

func readFile(filePath string) ([]byte, error) {
    file, err := os.Open(filePath)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    data := make([]byte, 1024)
    n, err := file.Read(data)
    if err != nil {
        return nil, err
    }
    return data[:n], nil
}

func main() {
    content, err := readFile("sample.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("File Content:", string(content))
}

Using this multiple return value pattern lets you quickly detect and handle errors at each stage of your code, making it easier to recover from unexpected situations and providing better feedback to users and developers.

Panic and Recover

Go has the panic and recovery mechanisms for exceptional cases. panic is used to halt the normal flow of the program and trigger a panic. In contrast, recover is used to catch and handle panics, allowing the program to continue execution gracefully.

It is important to use panic and recover sparingly and only for exceptional situations, such as unrecoverable errors.

package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()

    // Example of triggering a panic
    panic("something went wrong")

    fmt.Println("This line will not be executed.")
}

Error handling in Go follows a pragmatic and straightforward approach, allowing you to create reliable and robust backend systems.

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board