Rust groups errors into two major categories: recoverable and unrecoverable errors, and Rust does not treat them the same by handling exceptions like other languages.
For recoverable errors, it will has the type Result<T, E>
and for unrecoverable errors, the panic!
macro will stops execution.
panic!
There are two ways to cause a panic in practice: by taking an action that causes the code to panic(i.e. access out of bound) or by explicitly calling the panic!
macro.
Result
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let greeting_file_result = File::open("hello.txt");
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error);
}
},
};
}
Shortcuts also exists for panic on error:
unwrap
: if the Resultvalue is the
Okvariant, this will return the value inside the
Ok. Else, this function will call the
panic!` macro for us
let greeting_file = File::open("hello.txt").unwrap();
expect
: this method let us choose the panic
error messages.
let greeting_file = File::open("hello.txt")
.expect("hello.txt should be included in this project");
Similarly, if we want to propagate the error, ?
could be used
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username_file = File::open("hello.txt")?;
let mut username = String::new();
username_file.read_to_string(&mut username)?;
Ok(username)
}
The ?
placed after a Result
value is defined to work like this: If the value of the Result
is an Ok
, the value inside the Ok
will get returned from this expression, and the program will continue. If the value is an Err
, the Err
will be returned from the whole function.
Notice that the ?
operator can only be used inside a function that returns Result
or Option