Tipos de Erros Dinâmicos
Às vezes, queremos permitir que qualquer tipo de erro seja retornado sem escrever nosso próprio enum cobrindo todas as possibilidades diferentes. O trait std::error::Error torna fácil criar um objeto trait que pode conter qualquer erro.
use std::error::Error;
use std::fs;
use std::io::Read;
fn read_count(path: &str) -> Result<i32, Box<dyn Error>> {
let mut count_str = String::new();
fs::File::open(path)?.read_to_string(&mut count_str)?;
let count: i32 = count_str.parse()?;
Ok(count)
}
fn main() {
fs::write("count.dat", "1i3").unwrap();
match read_count("count.dat") {
Ok(count) => println!("Contagem: {count}"),
Err(err) => println!("Erro: {err}"),
}
}
A função read_count pode retornar std::io::Error (de operações de arquivo) ou std::num::ParseIntError (de String::parse).
Encaixotar (boxing) erros economiza código, mas sacrifica a capacidade de lidar elegantemente com diferentes casos de erro de forma individualizada no programa. Como tal, geralmente não é uma boa ideia usar Box<dyn Error> na API pública de uma biblioteca, mas pode ser uma boa opção em um programa onde você só quer exibir a mensagem de erro em algum lugar.
Certifique-se de implementar o trait std::error::Error ao definir um tipo de erro personalizado para que ele possa ser encaixotado. Mas se você precisa suportar o atributo no_std, tenha em mente que o trait std.error::Error é atualmente compatível com no_std apenas em nightly.