SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
12.11.2024

Lição: 009: Tratamento de Erros em Rust

O tratamento de erros é um aspecto crucial da programação. Em Rust, isso é feito através de uma combinação dos tipos Result e Option, que permitem aos desenvolvedores gerenciar e propagar erros de uma maneira mais robusta em comparação ao tratamento de exceções tradicional.

O Tipo Result

Em Rust, o tipo Result é usado para funções que podem retornar um erro. Ele é definido da seguinte forma:

enum Result<T, E> {
    Ok(T),
    Err(E),
}

Aqui, T é o tipo do valor que será retornado em caso de sucesso, e E é o tipo do erro que pode ocorrer.

Uso Básico do Result

Abaixo está um exemplo simples de como usar o tipo Result:

fn dividir(numerador: f64, denominador: f64) -> Result<f64, String> {
    if denominador == 0.0 {
        return Err("Não é possível dividir por zero".to_string());
    }
    Ok(numerador / denominador)
}

fn main() {
    match dividir(10.0, 2.0) {
        Ok(resultado) => println!("Resultado: {}", resultado),
        Err(e) => println!("Erro: {}", e),
    }

    match dividir(10.0, 0.0) {
        Ok(resultado) => println!("Resultado: {}", resultado),
        Err(e) => println!("Erro: {}", e),
    }
}

Explicação

  • A função dividir tenta dividir dois números. Se o denominador for zero, ela retorna um erro; caso contrário, retorna o resultado encapsulado em Ok.
  • Na função main, tratamos o resultado usando correspondência de padrões. Se o resultado for Ok, imprimimos o resultado; se for Err, imprimimos a mensagem de erro.

O Tipo Option

O tipo Option é usado para casos em que um valor pode estar ausente. Ele é definido como:

enum Option<T> {
    Some(T),
    None,
}

Uso Básico do Option

Aqui está uma função simples que recupera um elemento de um vetor:

fn obter_elemento(vec: &Vec<i32>, indice: usize) -> Option<i32> {
    if indice < vec.len() {
        Some(vec[indice])
    } else {
        None
    }
}

fn main() {
    let numeros = vec![1, 2, 3, 4, 5];

    match obter_elemento(&numeros, 2) {
        Some(valor) => println!("Elemento encontrado: {}", valor),
        None => println!("Nenhum elemento encontrado neste índice"),
    }

    match obter_elemento(&numeros, 10) {
        Some(valor) => println!("Elemento encontrado: {}", valor),
        None => println!("Nenhum elemento encontrado neste índice"),
    }
}

Explicação

  • A função obter_elemento verifica se o índice fornecido é válido para o vetor. Se válido, retorna Some(valor), caso contrário, retorna None.
  • Assim como com Result, usamos correspondência de padrões em main para lidar com a presença ou ausência de um valor.

Erros em Rust

Embora Result e Option sejam tipos poderosos para tratamento de erros, Rust oferece um tratamento de erros mais sofisticado através do operador ?. Isso pode simplificar o código ao propagar erros automaticamente.

Propagando Erros com ?

Aqui está um exemplo que combina manipulação de arquivos e propagação de erros:

use std::fs::File;
use std::io::{self, Read};

fn ler_nome_usuario_do_arquivo() -> Result<String, io::Error> {
    let mut f = File::open("nome_usuario.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

fn main() {
    match ler_nome_usuario_do_arquivo() {
        Ok(nome_usuario) => println!("Nome de usuário: {}", nome_usuario),
        Err(e) => println!("Erro ao ler o nome de usuário: {}", e),
    }
}

Explicação

  • A função ler_nome_usuario_do_arquivo tenta abrir um arquivo e ler seu conteúdo. O operador ? converte automaticamente qualquer erro do tipo Result em um retorno antecipado da função.
  • Na função main, tratamos o resultado da mesma forma que antes, imprimindo o nome de usuário ou uma mensagem de erro.

Conclusão

A abordagem de Rust para o tratamento de erros promove segurança e clareza no seu código ao tornar os erros explícitos. Utilizando Result e Option, você possui ferramentas poderosas para gerenciar erros, enquanto o operador ? simplifica a propagação de erros. À medida que você se familiariza mais com o tratamento de erros em Rust, perceberá que isso leva a um código mais confiável e de fácil manutenção. Boas codificações!

Did you like this article? Rate it from 1 to 5:

Thank you for voting!