Exception Handling → Error Values
Dealing with failures
Introduction
In this lesson, you'll learn about exception handling → error values in Go. Coming from Java, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In Java, you're familiar with dealing with failures.
Go has its own approach to dealing with failures, which we'll explore step by step.
The Go Way
Let's see how Go handles this concept. Here's a typical example:
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("not found")
func findUser(id int) (*User, error) {
u, ok := users[id]
if !ok {
return nil, fmt.Errorf("user %d: %w", id, ErrNotFound)
}
return u, nil
}
u, err := findUser(42)
if err != nil {
if errors.Is(err, ErrNotFound) {
fmt.Println("not found:", err)
} else {
fmt.Println("error:", err)
}
return
}
process(u)
defer cleanup() // defer = always runs, like finallyComparing to Java
Here's how you might have written similar code in Java:
// Checked exception — must declare/catch
public class NotFoundException extends Exception {
public NotFoundException(String msg) { super(msg); }
}
public User findUser(int id) throws NotFoundException {
if (!users.containsKey(id))
throw new NotFoundException("User " + id);
return users.get(id);
}
try {
User u = findUser(42);
process(u);
} catch (NotFoundException e) {
System.out.println("not found: " + e.getMessage());
} finally {
cleanup();
}You may be used to different syntax or behavior.
Go returns errors as values; Java throws exceptions
You may be used to different syntax or behavior.
Go has no try/catch — use if err != nil
You may be used to different syntax or behavior.
Go defer replaces Java finally for cleanup
You may be used to different syntax or behavior.
Go errors.Is() checks the error chain; Java instanceof for catch types
Step-by-Step Breakdown
1. Error Return Values
Go functions return (result, error) — no exceptions, no try/catch. Every call site must check the error explicitly.
try { User u = findUser(id); } catch (NotFoundException e) { ... }u, err := findUser(id)
if err != nil { /* handle */ }2. defer vs finally
Go's defer runs when the surrounding function returns — like Java's finally, but more concise and can be used anywhere.
} finally { cleanup(); }defer cleanup() // runs on function exit3. errors.Is vs instanceof
errors.Is checks the entire error chain (wrapped errors included). Java's catch clause uses instanceof implicitly.
catch (NotFoundException e) { ... }if errors.Is(err, ErrNotFound) { ... }Common Mistakes
When coming from Java, developers often make these mistakes:
- Go returns errors as values; Java throws exceptions
- Go has no try/catch — use if err != nil
- Go defer replaces Java finally for cleanup
Key Takeaways
- Go returns errors; Java throws exceptions
- if err != nil replaces try/catch
- defer replaces finally for cleanup
- errors.Is works through wrapped error chains