← Back to Rust Course | Chapter 10: Error Handling | Lesson 1 of 6

The Result Type

Result is Rust's way of saying an operation either worked and gives you an answer, or failed and tells you why.
Syntax
rust
enum Result<T, E> {
    Ok(T),
    Err(E),
}

match result {
    Ok(value) => expression,
    Err(e) => expression,
}

What Is Result

Result<T, E> is an enum with two variants: Ok(value) for success carrying a T, and Err(error) for failure carrying an E. It's the standard way Rust represents fallible operations.

Example: What Is Result

markup
// Define the function `divide` taking `a`, `b` and returning a `Result<f64, String>`
fn divide(a: f64, b: f64) -> Result<f64, String> {
    // Check whether `b == 0.0`
    if b == 0.0 {
        Err(String::from("division by zero"))
    // Otherwise, run this branch
    } else {
        Ok(a / b)
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Print "{:?}" to the console, substituting in `divide(10.0, 2.0)` (with a trailing newline)
    println!("{:?}", divide(10.0, 2.0));
}

Matching on Result

match lets you explicitly handle both the success and failure cases of a Result, extracting the value or the error as needed.

Example: Matching on Result

markup
// Define the function `divide` taking `a`, `b` and returning a `Result<f64, String>`
fn divide(a: f64, b: f64) -> Result<f64, String> {
    // Check whether `b == 0.0`
    if b == 0.0 {
        Err(String::from("division by zero"))
    // Otherwise, run this branch
    } else {
        Ok(a / b)
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Match on `divide(5.0, 0.0)` and branch by pattern
    match divide(5.0, 0.0) {
        Ok(value) => println!("Result: {}", value),
        Err(e) => println!("Error: {}", e),
    }
}

Parsing Returns a Result

Many standard library operations that can fail, like parsing a string into a number, return a Result so the caller must decide how to handle a malformed input.

Example: Parsing Returns a Result

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `input`, set to `"42"`
    let input = "42";
    // Declare an immutable variable `parsed` (a `Result<i32, _>`), set to `input.parse()`
    let parsed: Result<i32, _> = input.parse();
    // Match on `parsed` and branch by pattern
    match parsed {
        Ok(n) => println!("Parsed number: {}", n),
        Err(_) => println!("Could not parse"),
    }
}

Result vs Option

Option signals whether a value is present at all, while Result additionally carries information about why an operation failed, making it the better choice whenever the reason for failure matters.

Example: Result vs Option

markup
// Define the function `safe_divide` taking `a`, `b` and returning a `Result<i32, String>`
fn safe_divide(a: i32, b: i32) -> Result<i32, String> {
    // Check whether `b == 0`
    if b == 0 {
        Err(String::from("cannot divide by zero"))
    // Otherwise, run this branch
    } else {
        Ok(a / b)
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Print "{:?}" to the console, substituting in `safe_divide(10, 2)` (with a trailing newline)
    println!("{:?}", safe_divide(10, 2));
    // Print "{:?}" to the console, substituting in `safe_divide(10, 0)` (with a trailing newline)
    println!("{:?}", safe_divide(10, 0));
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Ignoring a Result returned by a function -- the compiler warns about an unused Result since errors could be silently dropped.
  2. Assuming Result and Option are interchangeable -- Result carries error information, while Option just signals absence.
  3. Trying to use the Ok value directly without matching or unwrapping the Result first.
Chapter Summary
  • Result<T, E> represents either success (Ok(value)) or failure (Err(error)).
  • Functions that can fail, like parsing or file I/O, typically return a Result instead of panicking directly.
  • match is the most explicit way to handle both the Ok and Err cases of a Result.
  • Rust's compiler warns when a Result is left unused, nudging you to handle potential errors.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.