What is Result<T, E>?
Rust replaces exceptions with Result<T, E>, an enum that's either Ok(value) on success or Err(error) on failure. Every function that can fail returns a Result, and the compiler forces you to handle both cases. No more unhandled exceptions crashing your program at runtime.
fn main() {
let success: Result<i32, String> = Ok(42);
let failure: Result<i32, String> = Err(String::from("something went wrong"));
println!("{:?}", success);
println!("{:?}", failure);
}
Try it Yourself ->
The ? Operator
The ? operator is Rust's secret weapon for clean error handling. If the Result is Ok, it unwraps the value. If it's Err, it returns early from the function with that error. No more match chains cluttering up your code.
use std::fs;
fn read_file(path: &str) -> Result<String, std::io::Error> {
let content = fs::read_to_string(path)?;
Ok(content)
}
fn main() {
match read_file("hello.txt") {
Ok(content) => println!("{}", content),
Err(e) => println!("Error: {}", e),
}
}
Try it Yourself ->
Unwrap and Expect
Just like with Option, you can use unwrap() on a Result โ it gives you the Ok value or panics. Use expect() instead when you want a custom panic message that explains what went wrong.
fn main() {
let num: Result<i32, &str> = Ok(10);
println!("{}", num.unwrap());
let num: Result<i32, &str> = Err("bad input");
// This would panic with message "bad input":
// println!("{}", num.expect("failed to parse"));
}
Try it Yourself ->
Combining Results with map_err and and_then
The map_err method converts the error type, which is handy when you want to unify different error types. and_then lets you chain functions that each return a Result, keeping your error handling clean and composable.
fn main() {
let num: Result<i32, &str> = Ok("42");
// map_err converts the error type
let result: Result<i32, String> = num.map_err(|e| format!("Error: {}", e));
println!("{:?}", result);
// and_then chains fallible operations
let value: Result<i32, &str> = Ok(5);
let result = value
.and_then(|v| if v > 0 { Ok(v * 2) } else { Err("too small") })
.and_then(|v| Ok(v + 10));
println!("{:?}", result);
}
Try it Yourself ->