Error Handling
Rust does not have exceptions. Instead, it uses:
Result<T, E>type for recoverable errorspanic!macro for unrecoverable errors
Panics
We can call panic! when there is no way out of the problem.
It terminates the program.
fn main() { panic!("fatal error");}Call stack
By default, when panic occurs we’ll only see the line in our code that led to
the panic. We can see the whole callstack by setting the RUST_BACKTRACE environment
variable to anything other than 0.
Recoverable Errors
Our functins might return Result if there is a chance of failure.
It’s brough in by the prelude.
enum Result<T, E> { Ok(T), Err(E),}An example of a built-in API that uses Result:
use std::fs::File;
fn main() { let f = File::open("hello.txt");
let f = match f { Ok(file) => file, Err(error) => panic!("Problem opening the file: {:?}", error), };}In this case we’re pacic!ing when error occurs.
Methods on Result
Result has some helper methods:
unwrap- returns value inside ofOk, orpanic!s if there’s error. It’s a shortcut which can be used instead ofmatch.expect- likeunwrap, but allows to specify error message for the potential panic.unwrap_or_else- returns value inside ofOkor executes a lambda passed to it in the case ofError.
The ? Operator
The ? placed after a Result value works as follows:
- if it’s
Ok(value), thevaluegets returned - if there’s an error, the containing function returns that error
? can convert the error to the expected Error type that a function
normally would return (theFrom trait needs to be implemented).
Example:
fn read_username_from_file() -> Result<String, io::Error> { let mut f = File::open("hello.txt")?; let mut s = String::new(); f.read_to_string(&mut s)?; Ok(s)}In the case above, ? does not need to convert the error since all the expected
errors would be of type io:Error - the same type that the function returns.