Back to Blog

Rust Error Handling - Result Enum, ? Operator & unwrap Methods | Beginner Tutorial

Sandy LaneSandy Lane

Video: Rust Error Handling - Result Enum, ? Operator & unwrap Methods | Beginner Tutorial by Taught by Celeste AI - AI Coding Coach

Watch full page →

Rust Error Handling - Result Enum, ? Operator & unwrap Methods

Rust uses the Result enum to handle errors explicitly, avoiding unexpected crashes by forcing you to manage success and failure cases. This tutorial demonstrates how to use Result with pattern matching, the ? operator for concise error propagation, and handy methods like unwrap and expect for working with results safely.

Code

fn divide(a: f64, b: f64) -> Result<f64, String> {
  if b == 0.0 {
    // Return an error if dividing by zero
    return Err(String::from("Cannot divide by zero!"));
  }
  // Return the division result wrapped in Ok
  Ok(a / b)
}

fn parse_number(s: &str) -> Result<i32, String> {
  s.trim().parse().map_err(|_| String::from("Invalid number"))
}

fn add_strings(a: &str, b: &str) -> Result<i32, String> {
  // Use ? to propagate errors automatically
  let num1 = parse_number(a)?;
  let num2 = parse_number(b)?;
  Ok(num1 + num2)
}

fn main() {
  // Handling Result with match
  match divide(10.0, 2.0) {
    Ok(result) => println!("10 / 2 = {}", result),
    Err(e) => println!("Error: {}", e),
  }

  match divide(10.0, 0.0) {
    Ok(result) => println!("10 / 0 = {}", result),
    Err(e) => println!("Error: {}", e),
  }

  // Using add_strings with ? operator
  match add_strings("10", "20") {
    Ok(sum) => println!("Sum: {}", sum),
    Err(e) => println!("Error: {}", e),
  }

  match add_strings("10", "abc") {
    Ok(sum) => println!("Sum: {}", sum),
    Err(e) => println!("Error: {}", e),
  }

  // Using unwrap and expect (panics on error)
  let valid = parse_number("42").unwrap();
  println!("Parsed with unwrap: {}", valid);

  // unwrap_or provides a fallback value on error
  let fallback = parse_number("not_a_number").unwrap_or(0);
  println!("Parsed with unwrap_or: {}", fallback);

  // unwrap_or_else uses a closure to compute fallback
  let fallback_else = parse_number("NaN").unwrap_or_else(|_| {
    println!("Parsing failed, using fallback");
    -1
  });
  println!("Parsed with unwrap_or_else: {}", fallback_else);
}

Key Points

  • The Result enum has two variants: Ok(value) for success and Err(error) for failure.
  • Pattern matching on Result forces you to handle both success and error cases explicitly.
  • The ? operator simplifies error propagation by returning early if an error occurs.
  • Methods like unwrap and expect extract values but panic on errors, so use them only when sure of success.
  • unwrap_or and unwrap_or_else provide safe fallback values to handle errors gracefully.