Result
Nosso mecanismo primário para tratamento de erros em Rust é o enum Result
, que vimos brevemente ao discutir tipos da biblioteca padrão.
use std::fs::File; use std::io::Read; fn main() { let file: Result<File, std::io::Error> = File::open("diary.txt"); match file { Ok(mut file) => { let mut contents = String::new(); if let Ok(bytes) = file.read_to_string(&mut contents) { println!("Querido diário: {contents} ({bytes} bytes)"); } else { println!("Não foi possível ler o conteúdo do arquivo"); } } Err(err) => { println!("Não foi possível abrir o diário: {err}"); } } }
-
Result
tem duas variantes:Ok
que contém o valor de sucesso, eErr
que contém um valor de erro de algum tipo. -
Se uma função pode ou não produzir um erro é codificado na assinatura de tipo da função, fazendo-a retornar um valor
Result
. -
Assim como com
Option
, não há como esquecer de lidar com um erro: você não pode acessar nem o valor de sucesso nem o valor de erro sem primeiro corresponder a um padrão noResult
para verificar qual variante você tem. Métodos comounwrap
facilitam a escrita de código rápido e sujo que não faz um tratamento de erros robusto, mas significa que você sempre pode ver em seu código-fonte onde o tratamento de erros adequado está sendo ignorado.
Mais para Explorar
Pode ser útil comparar o tratamento de erros em Rust com convenções de tratamento de erros com as quais os alunos podem estar familiarizados de outras linguagens de programação.
Exceções
-
Muitas linguagens usam exceções, por exemplo, C++, Java, Python.
-
Na maioria das linguagens com exceções, se uma função pode ou não lançar uma exceção não é visível como parte de sua assinatura de tipo. Isso geralmente significa que você não pode dizer ao chamar uma função se ela pode lançar uma exceção ou não.
-
Exceções geralmente desmontam a pilha de chamadas, propagando-se para cima até que um bloco
try
seja alcançado. Um erro originado profundamente na pilha de chamadas pode impactar uma função não relacionada mais acima.
Números de Erro
-
Algumas linguagens têm funções que retornam um número de erro (ou algum outro valor de erro) separadamente do valor de retorno bem-sucedido da função. Exemplos incluem C e Go.
-
Dependendo da linguagem, pode ser possível esquecer de verificar o valor de erro, caso em que você pode estar acessando um valor de sucesso não inicializado ou de outra forma inválido.