Result::unwrap() / expect() / ? Operator
Methods for extracting values from Result, and the ? operator for automatically propagating errors to the caller. The ? operator in particular can significantly reduce error-handling boilerplate.
Syntax
// Returns the value if Ok, or panics if Err.
let value = result.unwrap();
// Panics with the specified message if Err.
let value = result.expect("error message");
// Returns the default value if Err.
let value = result.unwrap_or(default_value);
// Propagates the error to the caller if Err (the ? operator).
// Can only be used inside a function that returns Result.
let value = some_func()?;
Method List
| Method / Operator | Description |
|---|---|
| unwrap() | Returns x if the value is Ok(x), or panics if it is Err. Avoid using this outside of prototypes and test code. |
| expect("msg") | Same as unwrap(), but displays the specified message on panic. Makes it easier to identify the cause of the error. |
| unwrap_or(val) | Returns the default value if the result is Err. Use this when you want to ignore the error and continue processing. |
| unwrap_or_else(fn) | Runs a closure that receives the error value when the result is Err(e). You can return a default value based on the error's content. |
| ? operator | Returns x if the value is Ok(x), or immediately returns the error to the caller if it is Err(e). Can only be used in functions that return Result (or Option). |
| ok() / err() | Converts a Result into an Option. ok() converts Ok(x) to Some(x) and Err to None. |
Sample Code
use std::num::ParseIntError;
// Propagates errors to the caller using the ? operator.
fn parse_and_double(s: &str) -> Result<i32, ParseIntError> {
let n = s.parse::<i32>()?; // Returns Err immediately if parsing fails.
Ok(n * 2)
}
// Example of chaining multiple ? operators.
fn parse_sum(a: &str, b: &str) -> Result<i32, ParseIntError> {
let x = a.parse::<i32>()?;
let y = b.parse::<i32>()?;
Ok(x + y)
}
fn main() {
// Calling functions that use the ? operator.
println!("{:?}", parse_and_double("5")); // Ok(10)
println!("{:?}", parse_and_double("abc")); // Err(...)
println!("{:?}", parse_sum("3", "4")); // Ok(7)
println!("{:?}", parse_sum("3", "x")); // Err(...)
// Using unwrap_or to fall back to a default value on error.
let n = "abc".parse::<i32>().unwrap_or(0);
println!("{}", n); // 0
// Using unwrap_or_else to handle the error value.
let n = "abc".parse::<i32>().unwrap_or_else(|e| {
println!("Parse error: {}", e);
-1
});
println!("{}", n); // -1
// Converting a Result to an Option with ok().
let opt = "42".parse::<i32>().ok();
println!("{:?}", opt); // Some(42)
}
Notes
The ? operator is syntactic sugar introduced in Rust 1.13 that reduces manual error-propagation code using match to a single character. The ? operator can only be used when the function's return type is Result or Option. To use it in main(), you must change the return type to Result<(), Box<dyn std::error::Error>>.
When error type conversion is needed, ? automatically calls the From trait to convert the error type. If your custom error type has the appropriate From implementation, you can use ? consistently even in functions that mix different error types.
If you find any errors or copyright issues, please contact us.