Skip to main content
Go Language Fundamentals for Beginners to Advanced
CHAPTER 16 Beginner

Error Handling in Go

Updated: May 17, 2026
5 min read

# CHAPTER 16

Error Handling in Go

1. Introduction

If you are coming from Python, Java, or C#, you are used to wrapping dangerous code in a try/catch block. If something explodes, the program jumps to the catch block.

Go does NOT have try/catch exceptions. Go believes that errors are a normal part of programming, not magical exceptions. In Go, errors are treated as normal values. Functions return errors, and you explicitly check them using if err != nil.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the error interface.
  • Check and handle returned errors properly.
  • Create custom errors using errors.New().
  • Format detailed errors using fmt.Errorf().
  • Understand panic and recover.

3. The error Interface

In Go, error is a built-in interface that has a single method: Error() string. If a function might fail, you design it to return multiple values: the result, AND an error.

If the operation succeeds, the error returned is nil. If it fails, it returns an error object containing a message.

4. Checking Errors (if err != nil)

Let's simulate parsing a string into an integer. The strconv package can fail if the string contains letters.
go
12345678910111213141516171819
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Atoi converts string to integer. Returns (int, error)
    price, err := strconv.Atoi("100abc")

    // EXPLICIT ERROR CHECKING
    if err != nil {
        fmt.Println("Failed to parse price:", err)
        return // Stop the program cleanly!
    }

    fmt.Println("The price is:", price)
}

*Note: You will write if err != nil hundreds of times in Go. It forces you to think about failure at every step.*

5. Creating Custom Errors

You can generate your own errors using the errors package.
go
12345678910111213141516171819202122
import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        // Create a basic error
        return 0, errors.New("cannot divide by zero") 
    }
    return a / b, nil // Return nil because there is no error
}

func main() {
    result, err := divide(10, 0)
    
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result)
    }
}

6. Formatting Detailed Errors

Often, a generic error isn't enough. You want to include variable data in the error message. Use fmt.Errorf(), which acts just like Printf, but generates an error object instead of printing to the console.
go
1234567
func findUser(id int) (string, error) {
    if id != 1 {
        // Generating a detailed, formatted error
        return "", fmt.Errorf("user with ID %d was not found in the database", id)
    }
    return "Alice", nil
}

7. Panic and Recover

If Go doesn't have exceptions, what happens if the program actually crashes (like dividing by zero, or accessing an out-of-bounds array)? This is called a Panic. A panic immediately stops execution and kills the program.

You can trigger a panic manually for completely unrecoverable situations (e.g., the server failed to start because the port is in use).

go
123
func main() {
    panic("CRITICAL SYSTEM FAILURE! Shutting down.")
}

Recover: If a Panic happens, you can catch it and prevent the application from crashing using recover() inside a defer statement. *(Note: defer executes a function at the very end, right before the surrounding function exits).*

go
12345678910111213141516
func safeExecution() {
    // defer runs this anonymous function right before safeExecution() finishes
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()

    fmt.Println("About to panic...")
    panic("Oops!") // This would normally crash the program
}

func main() {
    safeExecution()
    fmt.Println("Program continues because we recovered!")
}

8. Common Mistakes

  • Ignoring Errors using : price, := strconv.Atoi("abc"). If it fails, price becomes 0 and you never know why. Never ignore errors in production code.
  • Overusing Panic: Beginners use panic like throw Exception in Java. In Go, panic is strictly for catastrophic, unrecoverable crashes. For normal logic flow (bad password, missing file), always return an error.

9. Best Practices

  • Error messages should be completely lowercase and should not end with punctuation. Go's standard libraries follow this to allow errors to be easily chained together. (e.g., errors.New("user not found") rather than "User not found!").

10. Exercises

  1. 1. Write a function checkPasswordLength(pwd string) error.
  1. 2. If the length is less than 8, return an error using fmt.Errorf.
  1. 3. Test it in main and print the result.

11. MCQs with Answers & Explanations

Q1. Does Go use try/catch exception blocks? a) Yes b) No Answer: b) No. *Explanation: Go returns errors as normal values.*

Question 2

What is the standard way to check if an operation failed in Go?

Question 3

If a function succeeds, what value should the error return be?

Question 4

Which package allows you to create a simple, basic error?

Question 5

Which function is used to create an error containing formatted variables (like %d)?

Question 6

What is a Panic in Go?

Q7. Is it good practice to use panic() for minor logic errors like a bad password? a) Yes b) No, you should return a standard error instead. Answer: b) No, you should return a standard error.
Question 8

Which keyword guarantees a function will run at the very end of the current function, even if a panic occurs?

Question 9

Which function can catch a panic and prevent the program from crashing?

Q10. What is a bad practice when dealing with multiple return values? a) Checking the error immediately b) Using the blank identifier _ to ignore the error completely Answer: b) Using the blank identifier to ignore the error.

12. Interview Preparation

Interview Questions:
  1. 1. Why did the Go creators choose to use explicit error checking (if err != nil) over try/catch exceptions?
  1. 2. Explain the difference between returning an error and triggering a panic.
  1. 3. How do defer, panic, and recover work together?

13. Summary

Go's error handling forces developers to confront failure directly. By treating errors as normal return values, the execution flow remains incredibly easy to trace. While if err != nil requires extra typing, it results in highly robust, predictable, and crash-resistant backend applications.

14. Next Chapter Recommendation

Our code is getting larger. Writing everything in one file is bad practice. In Chapter 17: Packages and Modules, we will learn how to organize our code into multiple files, create reusable packages, and manage external dependencies.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·