Custom Errors in Rust

It’s possible to use custom types as errors by implementing the Error trait on them. Here’s an example that uses a custom type to explicitly represent an argument error.

use std::fmt;
use std::error::Error;

// A custom error type usually has the suffix "Error".
#[derive(Debug)]
struct ArgError {
    arg: i32,
    message: String,
}

// Implementing the Display trait for our custom error
impl fmt::Display for ArgError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} - {}", self.arg, self.message)
    }
}

// Implementing the Error trait for our custom error
impl Error for ArgError {}

fn f(arg: i32) -> Result<i32, ArgError> {
    if arg == 42 {
        // Return our custom error.
        Err(ArgError { arg, message: String::from("can't work with it") })
    } else {
        Ok(arg + 3)
    }
}

fn main() {
    // The `downcast_ref` method is similar to `errors.As` in Go.
    // It attempts to downcast the error to a concrete type.
    let result = f(42);
    if let Err(e) = result {
        if let Some(ae) = e.downcast_ref::<ArgError>() {
            println!("{}", ae.arg);
            println!("{}", ae.message);
        } else {
            println!("err doesn't match ArgError");
        }
    }
}

In this Rust version:

  1. We define a custom ArgError struct that implements both the Display and Error traits. This is equivalent to implementing the error interface in Go.

  2. The f function returns a Result<i32, ArgError> instead of (int, error). This is Rust’s idiomatic way of handling errors.

  3. In the main function, we use pattern matching (if let) to handle the Result returned by f. This is similar to error checking in Go.

  4. To check if the error is of our custom type, we use the downcast_ref method, which is similar to errors.As in Go. It attempts to downcast the error to a concrete type.

To run the program:

$ rustc custom_errors.rs
$ ./custom_errors
42
can't work with it

This example demonstrates how to create and use custom error types in Rust, which provides a similar level of flexibility for error handling as Go.