Ferrugem - Tratamento de Erros
Em Rust, os erros podem ser classificados em duas categorias principais, conforme mostrado na tabela abaixo.
Sr. Não | Nome e Descrição | Uso |
---|---|---|
1 | Recoverable Erros que podem ser tratados |
Resultado enum |
2 | UnRecoverable Erros que não podem ser tratados |
macro de pânico |
Um erro recuperável é um erro que pode ser corrigido. Um programa pode tentar novamente a operação que falhou ou especificar um curso de ação alternativo ao encontrar um erro recuperável. Erros recuperáveis não fazem com que um programa falhe abruptamente. Um exemplo de erro recuperável é o erro Arquivo não encontrado .
Erros irrecuperáveis fazem com que um programa falhe abruptamente. Um programa não pode voltar ao seu estado normal se ocorrer um erro irrecuperável. Ele não pode repetir a operação com falha ou desfazer o erro. Um exemplo de erro irrecuperável é tentar acessar um local além do final de uma matriz.
Ao contrário de outras linguagens de programação, Rust não tem exceções. Ele retorna um resultado enum <T, E> para erros recuperáveis, enquanto chama opanicmacro se o programa encontrar um erro irrecuperável. A macro de pânico faz com que o programa seja encerrado abruptamente.
Macro de pânico e erros irrecuperáveis
pânico! macro permite que um programa termine imediatamente e forneça feedback ao chamador do programa. Deve ser usado quando um programa atinge um estado irrecuperável.
fn main() {
panic!("Hello");
println!("End of main"); //unreachable statement
}
No exemplo acima, o programa será encerrado imediatamente quando encontrar o pânico! macro.
Resultado
thread 'main' panicked at 'Hello', main.rs:3
Ilustração: pânico! macro
fn main() {
let a = [10,20,30];
a[10]; //invokes a panic since index 10 cannot be reached
}
A saída é como mostrado abaixo -
warning: this expression will panic at run-time
--> main.rs:4:4
|
4 | a[10];
| ^^^^^ index out of bounds: the len is 3 but the index is 10
$main
thread 'main' panicked at 'index out of bounds: the len
is 3 but the index is 10', main.rs:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Um programa pode invocar o pânico! macro se as regras de negócios forem violadas, conforme mostrado no exemplo abaixo -
fn main() {
let no = 13;
//try with odd and even
if no%2 == 0 {
println!("Thank you , number is even");
} else {
panic!("NOT_AN_EVEN");
}
println!("End of main");
}
O exemplo acima retorna um erro se o valor atribuído à variável for ímpar.
Resultado
thread 'main' panicked at 'NOT_AN_EVEN', main.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Resultado Enum e erros recuperáveis
Resultado Enum - <T, E> pode ser usado para tratar erros recuperáveis. Possui duas variantes -OK e Err. T e E são parâmetros de tipo genérico. T representa o tipo de valor que será retornado em um caso de sucesso dentro da variante OK, e E representa o tipo de erro que será retornado em um caso de falha na variante Err.
enum Result<T,E> {
OK(T),
Err(E)
}
Vamos entender isso com a ajuda de um exemplo -
use std::fs::File;
fn main() {
let f = File::open("main.jpg");
//this file does not exist
println!("{:?}",f);
}
O programa retorna OK (Arquivo) se o arquivo já existe e Err (Erro) se o arquivo não for encontrado.
Err(Error { repr: Os { code: 2, message: "No such file or directory" } })
Vamos agora ver como lidar com a variante Err.
O exemplo a seguir lida com um erro retornado ao abrir o arquivo usando o match declaração
use std::fs::File;
fn main() {
let f = File::open("main.jpg"); // main.jpg doesn't exist
match f {
Ok(f)=> {
println!("file found {:?}",f);
},
Err(e)=> {
println!("file not found \n{:?}",e); //handled error
}
}
println!("end of main");
}
NOTE- O programa imprime o final do evento principal , embora o arquivo não tenha sido encontrado. Isso significa que o programa tratou os erros de maneira adequada.
Resultado
file not found
Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
end of main
Ilustração
A função is_even retorna um erro se o número não for um número par. A função main () lida com esse erro.
fn main(){
let result = is_even(13);
match result {
Ok(d)=>{
println!("no is even {}",d);
},
Err(msg)=>{
println!("Error msg is {}",msg);
}
}
println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
if no%2==0 {
return Ok(true);
} else {
return Err("NOT_AN_EVEN".to_string());
}
}
NOTE- Uma vez que a função principal lida com erros normalmente, o final da instrução principal é impresso.
Resultado
Error msg is NOT_AN_EVEN
end of main
desembrulhe () e espere ()
A biblioteca padrão contém alguns métodos auxiliares que ambas as enums - Result <T, E> e Option <T> implementam. Você pode usá-los para simplificar os casos de erro em que você realmente não espera que as coisas falhem. Em caso de sucesso de um método, a função "desembrulhar" é usada para extrair o resultado real.
Sr. Não | Método | Assinatura e Descrição |
---|---|---|
1 | desembrulhar | unwrap(self): T Espera-se estar Ok / Algum e retorna o valor contido em. Se forErr ou None em vez disso, causa pânico com o conteúdo do erro exibido. |
2 | Espero | expect(self, msg: &str): T Comporta-se como desembrulhar, exceto que ele produz uma mensagem personalizada antes de entrar em pânico, além do conteúdo do erro. |
desembrulhar()
A função unbrap () retorna o resultado real de uma operação bem-sucedida. Ele retorna um pânico com uma mensagem de erro padrão se uma operação falhar. Esta função é uma abreviatura para declaração de correspondência. Isso é mostrado no exemplo abaixo -
fn main(){
let result = is_even(10).unwrap();
println!("result is {}",result);
println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
if no%2==0 {
return Ok(true);
} else {
return Err("NOT_AN_EVEN".to_string());
}
}
result is true
end of main
Modifique o código acima para passar um número ímpar para o is_even() função.
A função unbrap () entrará em pânico e retornará uma mensagem de erro padrão como mostrado abaixo
thread 'main' panicked at 'called `Result::unwrap()` on
an `Err` value: "NOT_AN_EVEN"', libcore\result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace
Espero()
O programa pode retornar uma mensagem de erro personalizada em caso de pânico. Isso é mostrado no seguinte exemplo -
use std::fs::File;
fn main(){
let f = File::open("pqr.txt").expect("File not able to open");
//file does not exist
println!("end of main");
}
A função expect () é semelhante a unbrap (). A única diferença é que uma mensagem de erro personalizada pode ser exibida usando esperar.
Resultado
thread 'main' panicked at 'File not able to open: Error { repr: Os
{ code: 2, message: "No such file or directory" } }', src/libcore/result.rs:860
note: Run with `RUST_BACKTRACE=1` for a backtrace.