The Result Type
What Is Result<T, E>?
Section titled “What Is Result<T, E>?”Result<T, E> is the standard Rust type for operations that can either succeed or fail in an expected way. It is defined in the standard library as:
enum Result<T, E> { Ok(T), Err(E),}Ok(T)— the operation succeeded and produced a value of typeT.Err(E)— the operation failed and produced an error value of typeE.
Both T and E are generic parameters you fill in. For example, Result<i32, String> succeeds with an i32 or fails with a String error message.
Returning a Result
Section titled “Returning a Result”To signal a recoverable failure from a function, change its return type to Result<T, E> and return Ok(value) on success or Err(error) on failure:
fn parse_age(s: &str) -> Result<u32, String> { s.parse::<u32>().map_err(|e| format!("parse error: {}", e))}The .map_err call converts the standard library’s parse error into your own String error type.
Handling a Result
Section titled “Handling a Result”The most explicit way to handle a Result is a match expression — it forces you to address both branches:
fn parse_age(s: &str) -> Result<u32, String> { s.parse::<u32>().map_err(|e| format!("parse error: {}", e))}
fn main() { match parse_age("25") { Ok(age) => println!("Parsed age: {}", age), Err(e) => println!("Error: {}", e), }}Convenience Methods
Section titled “Convenience Methods”For less verbose code, Result provides several methods:
| Method | Behaviour |
|---|---|
.unwrap() | Returns the Ok value; panics on Err |
.expect(msg) | Same, but with a custom panic message |
.unwrap_or(default) | Returns the Ok value or a default |
.unwrap_or_else(|e| ...) | Returns the Ok value or computes a default from the error |
.is_ok() / .is_err() | Boolean tests without extracting the value |
.map(|v| ...) | Transforms the Ok value, leaves Err unchanged |
.map_err(|e| ...) | Transforms the Err value, leaves Ok unchanged |
fn parse_age(s: &str) -> Result<u32, String> { s.parse::<u32>().map_err(|e| format!("parse error: {}", e))}
fn main() { // Match on Result to handle both branches match parse_age("25") { Ok(age) => println!("Parsed age: {}", age), Err(e) => println!("Error: {}", e), }
// .unwrap_or returns a default on Err let age1 = parse_age("abc").unwrap_or(0); println!("unwrap_or default: {}", age1);
// .unwrap_or_else lets you compute the default let age2 = parse_age("not_a_number").unwrap_or_else(|e| { println!("Recovering from: {}", e); 18 }); println!("unwrap_or_else result: {}", age2);
// is_ok / is_err for simple checks println!("parse_age(\"30\") is_ok: {}", parse_age("30").is_ok()); println!("parse_age(\"xx\") is_err: {}", parse_age("xx").is_err());}Compiling…