AnyCompiler

Tratamento de Erros

O operador ? é uma forma abreviada de propagar um Result: se a expressão for Err, ? retorna esse erro imediatamente da função atual; se for Ok, ? desembrulha o valor e a execução continua. s.parse()? abaixo ou te dá um i32 válido ou sai antecipadamente de parse_and_double com o erro de parse.

use std::num::ParseIntError;

fn parse_and_double(s: &str) -> Result<i32, ParseIntError> {
    let n: i32 = s.parse()?;
    Ok(n * 2)
}

fn main() {
    match parse_and_double("21") {
        Ok(n) => println!("Doubled: {}", n),
        Err(e) => println!("Error: {}", e),
    }

    match parse_and_double("not a number") {
        Ok(n) => println!("Doubled: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}
Output
Doubled: 42
Error: invalid digit found in string

Um tipo de erro personalizado

Para suas próprias funções, um tipo de erro personalizado — mesmo um simples como NegativeNumberError — costuma ser mais claro do que reutilizar um erro genérico. Implementar o trait Display para ele é o que permite que {} o formate diretamente dentro de println!.

use std::fmt;

#[derive(Debug)]
struct NegativeNumberError;

impl fmt::Display for NegativeNumberError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "number must not be negative")
    }
}

fn square_root_ish(n: i32) -> Result<f64, NegativeNumberError> {
    if n < 0 {
        return Err(NegativeNumberError);
    }
    Ok((n as f64).sqrt())
}

fn main() {
    match square_root_ish(16) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }

    match square_root_ish(-4) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }
}
Output
Result: 4
Error: number must not be negative

Próximo: collections e a biblioteca padrão — HashMap, e um último olhar sobre o que mais a biblioteca padrão do Rust oferece.

Practice Exercise

Escreva uma função safe_divide(a: f64, b: f64) -> Result<f64, String> que retorne Err("cannot divide by zero".to_string()) se b for 0.0, ou Ok(a / b) caso contrário. Chame-a com (10.0, 0.0), faça match do resultado, e imprima a mensagem de erro se for Err.