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:
We define a custom
ArgError
struct that implements both theDisplay
andError
traits. This is equivalent to implementing theerror
interface in Go.The
f
function returns aResult<i32, ArgError>
instead of(int, error)
. This is Rust’s idiomatic way of handling errors.In the
main
function, we use pattern matching (if let
) to handle theResult
returned byf
. This is similar to error checking in Go.To check if the error is of our custom type, we use the
downcast_ref
method, which is similar toerrors.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.