Result<T, E> / Ok / Err
Result<T, E> is an enum that represents the outcome of an operation as either success (Ok) or failure (Err). Instead of exceptions, Rust uses Result to force you to handle potential errors at compile time.
Syntax
// Wrap a success value in Ok.
let ok: Result<i32, String> = Ok(42);
// Wrap an error value in Err.
let err: Result<i32, String> = Err(String::from("An error occurred."));
// Use match to branch on success or failure.
match result {
Ok(value) => println!("Success: {}", value),
Err(e) => println!("Failure: {}", e),
}
// Use if let to handle only the success case.
if let Ok(value) = result {
println!("Success: {}", value);
}
Syntax reference
| Syntax / Variant | Description |
|---|---|
| Ok(value) | A variant indicating that the operation succeeded. Holds the resulting success value. |
| Err(error) | A variant indicating that the operation failed. Holds details about the error. Any type can be used as the error type. |
| match | Branches on the two patterns Ok(v) and Err(e). Both arms are required, preventing you from accidentally ignoring errors. |
| if let Ok(v) | Syntactic sugar for handling only the success case. Avoid overusing it, as it silently ignores errors. |
| is_ok() / is_err() | Returns a boolean indicating whether the result is a success or failure. Use these when you only need to check the state without processing the value. |
Sample code
// A function that divides two numbers and returns Err on division by zero.
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err(String::from("Cannot divide by zero."))
} else {
Ok(a / b)
}
}
fn main() {
// Handle the success case with match.
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
// Handle the failure case with match.
match divide(10.0, 0.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
// Check the state with is_ok / is_err.
let r1 = divide(10.0, 2.0);
let r2 = divide(10.0, 0.0);
println!("r1 is_ok: {}", r1.is_ok()); // true
println!("r2 is_err: {}", r2.is_err()); // true
// Parsing from the standard library also returns a Result.
let parsed: Result<i32, _> = "42".parse();
println!("{:?}", parsed); // Ok(42)
let failed: Result<i32, _> = "abc".parse();
println!("{:?}", failed); // Err(...)
}
Notes
In the type parameter Result<T, E>, T is the type of the success value and E is the type of the error value. You can use any type for the error, such as the standard library's std::io::Error or a custom type. If you discard the return value of a function that returns Result without using it, the compiler will issue a warning. Always handle errors explicitly, or explicitly ignore them.
Almost every operation in Rust's standard library that can fail — file I/O, networking, parsing, and more — returns a Result. This is the Rust equivalent of try-catch in other languages. Because Rust has no exceptions, treating errors as explicit return values is the idiomatic Rust approach.
If you find any errors or copyright issues, please contact us.