Учебники

Rust — Обработка ошибок

В Rust ошибки можно разделить на две основные категории, как показано в таблице ниже.

Sr.No Имя и описание использование
1

Извлекаемые

Ошибки, которые могут быть обработаны

Результат enum
2

UNRECOVERABLE

Ошибки, которые не могут быть обработаны

макрос паники

Извлекаемые

Ошибки, которые могут быть обработаны

UNRECOVERABLE

Ошибки, которые не могут быть обработаны

Исправимая ошибка — это ошибка, которую можно исправить. Программа может повторить неудачную операцию или указать альтернативный порядок действий при обнаружении исправимой ошибки. Исправимые ошибки не приводят к внезапному сбою программы. Примером исправимой ошибки является ошибка « Файл не найден» .

Неустранимые ошибки приводят к внезапному сбою программы. Программа не может вернуться к своему нормальному состоянию, если возникает неисправимая ошибка. Он не может повторить неудачную операцию или отменить ошибку. Пример неисправимой ошибки — попытка получить доступ к расположению за концом массива.

В отличие от других языков программирования, Rust не имеет исключений. Он возвращает Enum Result <T, E> для исправляемых ошибок, а также вызывает макрос паники, если программа обнаруживает неисправимую ошибку. Макрос паники вызывает внезапное завершение программы.

Макрос паники и неисправимые ошибки

паника! макрос позволяет программе немедленно завершать работу и предоставлять обратную связь вызывающей программе. Его следует использовать, когда программа достигает неисправимого состояния.

fn main() {
   panic!("Hello");
   println!("End of main"); //unreachable statement
}

В приведенном выше примере, программа будет завершена немедленно, когда она сталкивается с паникой! макро.

Выход

thread 'main' panicked at 'Hello', main.rs:3

Иллюстрация: паника! макрос

fn main() {
   let a = [10,20,30];
   a[10]; //invokes a panic since index 10 cannot be reached
}

Вывод как показано ниже —

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.

Программа может вызвать панику! макрос, если бизнес-правила нарушаются, как показано в примере ниже —

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");
}

Приведенный выше пример возвращает ошибку, если значение, присвоенное переменной, является нечетным.

Выход

thread 'main' panicked at 'NOT_AN_EVEN', main.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Перечисление результата и исправимые ошибки

Enum Result — <T, E> может использоваться для обработки исправимых ошибок. У него есть два варианта — OK и Err . T и E — параметры универсального типа. T представляет тип значения, которое будет возвращено в случае успеха в варианте OK, а E представляет тип ошибки, которая будет возвращена в случае ошибки в варианте Err.

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

Позвольте нам понять это с помощью примера —

use std::fs::File;
fn main() {
   let f = File::open("main.jpg"); 
   //this file does not exist
   println!("{:?}",f);
}

Программа возвращает OK (Файл), если файл уже существует, и Err (Ошибка), если файл не найден.

Err(Error { repr: Os { code: 2, message: "No such file or directory" } })

Давайте теперь посмотрим, как работать с вариантом Err.

В следующем примере обрабатывается ошибка, возвращаемая при открытии файла с помощью оператора match

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");
}

ПРИМЕЧАНИЕ. — Программа печатает конец основного события, хотя файл не был найден. Это означает, что программа корректно обработала ошибку.

Выход

file not found
Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
end of main

иллюстрация

Функция is_even возвращает ошибку, если число не является четным числом. Функция main () обрабатывает эту ошибку.

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());
   }
}

ПРИМЕЧАНИЕ. — Так как основная функция корректно обрабатывает ошибки, выводится конец основного оператора.

Выход

Error msg is NOT_AN_EVEN
end of main

развернуть () и ожидать ()

Стандартная библиотека содержит несколько вспомогательных методов, которые оба перечисляют — Result <T, E> и Option <T> . Вы можете использовать их для упрощения случаев ошибок, когда вы действительно не ожидаете, что что-то не получится. В случае успеха метода, функция «развернуть» используется для извлечения фактического результата.

Sr.No метод Подпись и описание
1 разворачивать

развернуть (самостоятельно): T

Ожидает, что self будет Ok / Some и вернет значение, содержащееся в. Если это Err или None, вместо этого возникает паника с содержанием отображаемой ошибки.

2 ожидать

ожидайте (self, msg: & str): T

Ведет себя как развертка, за исключением того, что выводит собственное сообщение перед паникой в ​​дополнение к содержанию ошибки.

развернуть (самостоятельно): T

Ожидает, что self будет Ok / Some и вернет значение, содержащееся в. Если это Err или None, вместо этого возникает паника с содержанием отображаемой ошибки.

ожидайте (self, msg: & str): T

Ведет себя как развертка, за исключением того, что выводит собственное сообщение перед паникой в ​​дополнение к содержанию ошибки.

Развертка ()

Функция unwrap () возвращает фактический результат успешной операции. В случае сбоя операции возвращается паника с сообщением об ошибке по умолчанию. Эта функция является сокращением для выражения соответствия. Это показано в примере ниже —

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

Измените приведенный выше код, чтобы передать нечетное число в функцию is_even () .

Функция unwrap () вызовет панику и вернет сообщение об ошибке по умолчанию, как показано ниже

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

ожидать ()

Программа может вернуть пользовательское сообщение об ошибке в случае паники. Это показано в следующем примере —

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");
}

Функция wait () похожа на unwrap (). Разница лишь в том, что пользовательское сообщение об ошибке может отображаться с использованием ожидаемого.