Error handling

Demo: error-handling

In Rust, there are 2 types of error.

| Recoverable | Unrecoverable | | -------------------------- | ---------------------------- | | Example: file not found | Example: index out of bounds | | Handle with Result<T, E> | Handle with panic! |

panic! stop the program immediately and provide feedback.

Result<T, E> enum

Similar to Option<T>, Result<T, E> wraps the value. It provides Ok and Err to make sure the error is catched.

enum Result<T, E> {
    Ok(T),
    Err(E)
}

It's included in prelude so we don't need to import it explictly.

To handle the error, we can use match.

// fs::read_to_string returns a Result
let result = fs::read_to_string("hello.txt");

let contents = match result {
    Ok(contents) => contents,
    Err(e) => panic!("There was a problem reading the file: {:?}", e),
};

Propagating errors

Sometimes, we want to propagate the errors from low level to high level, then deal with it. For example, we create a read_file function and call it.

fn read_file(file_name: &str) -> Result<String, io::Error> {
    let result = match fs::read_to_string(file_name) {
        Ok(string) => string,
        Err(error) => return Err(error),
    };
    Ok(result)
}

fn main() {
    let file_string = read_file("src/test.txt");
    let contents = match file_string {
        Ok(contents) => contents,
        Err(e) => panic!("There was a problem reading the file: {:?}", e),
    };
    println!("{}", contents);
}

We've writen match 2 times. There is a way to prograte it. We don't handle with the error in read_file function, only in the main function.

fn read_file(file_name: &str) -> Result<String, io::Error> {
    let result = fs::read_to_string(file_name)?;
    Ok(result)
}

Attention: It only works with the function returns a Result.