Google News
logo
Rust - Interview Questions
How does error handling work in Rust?
Error handling in Rust is based on the concept of "recoverable" errors, where errors are represented using the `Result<T, E>` type. This approach encourages explicit handling of errors and helps prevent runtime errors and unexpected panics.

The `Result<T, E>` type is an enumeration with two variants:
* `Ok(T)`: Represents a successful result with a value of type `T`.
* `Err(E)`: Represents an error condition with an associated value of type `E`.

Here's an overview of how error handling works in Rust:

1. Returning Results : Functions that can produce errors typically return `Result<T, E>`. By convention, the `Result` type is used to indicate that an operation can result in either a successful value (`Ok`) or an error (`Err`).

Example :
fn parse_number(s: &str) -> Result<i32, ParseIntError> {
    match s.parse::<i32>() {
        Ok(num) => Ok(num),
        Err(err) => Err(err),
    }
}​

2. Propagating Errors : When calling a function that returns `Result`, you have to handle the potential errors. You can either use pattern matching (`match`), or you can utilize the `?` operator, known as the "try" operator, to propagate errors.

Example using `match`:
fn double_number(s: &str) -> Result<i32, ParseIntError> {
    let num = match parse_number(s) {
        Ok(num) => num * 2,
        Err(err) => return Err(err),
    };
    Ok(num)
}​

Example using `?` operator :
fn double_number(s: &str) -> Result<i32, ParseIntError> {
    let num = parse_number(s)?;
    Ok(num * 2)
}​

The `?` operator unwraps the `Result` value and returns the underlying value if it's `Ok`. If the value is `Err`, the `?` operator short-circuits the function, returning the `Err` value from the enclosing function.

3. Error Handling with `match`: Pattern matching (`match`) is commonly used to handle different error conditions explicitly. You can match on specific error variants and execute specific code blocks based on the error type.

Example :
fn handle_error(result: Result<i32, ParseIntError>) {
    match result {
        Ok(num) => println!("Parsed number: {}", num),
        Err(ParseIntError { .. }) => println!("Failed to parse integer"),
    }
}​

4. Propagating Errors with `?` in `main()`: When handling errors in the `main()` function, you can use the `?` operator to automatically propagate errors, which will cause the program to exit and display the error if one occurs.

Example :
fn main() -> Result<(), Box<dyn Error>> {
    let result = double_number("42")?;
    println!("Doubled number: {}", result);
    Ok(())
}​
Advertisement