Rust - Xử lý lỗi

Trong Rust, các lỗi có thể được phân thành hai loại chính như trong bảng dưới đây.

Sr.No Tên & Mô tả Sử dụng
1

Recoverable

Các lỗi có thể được xử lý

Kết quả enum
2

UnRecoverable

Các lỗi không thể xử lý

vĩ mô hoảng loạn

Lỗi có thể khôi phục là lỗi có thể sửa được. Một chương trình có thể thử lại thao tác không thành công hoặc chỉ định một hướng hành động thay thế khi nó gặp lỗi có thể khôi phục được. Các lỗi có thể khôi phục không làm cho chương trình bị lỗi đột ngột. Một ví dụ về lỗi có thể khôi phục là lỗi Không tìm thấy tệp .

Các lỗi không thể khôi phục khiến chương trình bị lỗi đột ngột. Một chương trình không thể trở lại trạng thái bình thường của nó nếu xảy ra lỗi không thể khôi phục. Nó không thể thử lại thao tác không thành công hoặc hoàn tác lỗi. Một ví dụ về lỗi không thể khôi phục đang cố gắng truy cập một vị trí nằm ngoài phần cuối của một mảng.

Không giống như các ngôn ngữ lập trình khác, Rust không có ngoại lệ. Nó trả về kết quả enum <T, E> cho các lỗi có thể khôi phục, trong khi nó gọipanicmacro nếu chương trình gặp lỗi không thể khôi phục. Các hoảng loạn vĩ mô làm cho chương trình để thoát đột ngột.

Macro hoảng sợ và các lỗi không thể khôi phục

hoảng loạn! macro cho phép một chương trình kết thúc ngay lập tức và cung cấp phản hồi cho người gọi chương trình. Nó nên được sử dụng khi một chương trình đạt đến trạng thái không thể khôi phục.

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

Trong ví dụ trên, chương trình sẽ kết thúc ngay lập tức khi gặp sự cố ! vĩ mô.

Đầu ra

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

Hình minh họa: hoảng sợ! vĩ mô

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

Đầu ra như hình dưới đây -

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.

Một chương trình có thể gây ra sự hoảng loạn! vĩ mô nếu các quy tắc kinh doanh bị vi phạm như được hiển thị trong ví dụ dưới đây -

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

Ví dụ trên trả về lỗi nếu giá trị được gán cho biến là số lẻ.

Đầu ra

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

Enum kết quả và lỗi có thể khôi phục

Kết quả Enum - <T, E> có thể được sử dụng để xử lý các lỗi có thể khôi phục được. Nó có hai biến thể -OKErr. TE là các tham số kiểu chung. T đại diện cho loại giá trị sẽ được trả lại trong trường hợp thành công trong biến thể OK và E đại diện cho loại lỗi sẽ được trả lại trong trường hợp lỗi trong biến thể Err.

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

Hãy để chúng tôi hiểu điều này với sự trợ giúp của một ví dụ -

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

Chương trình trả về OK (Tệp) nếu tệp đã tồn tại và Err (Lỗi) nếu không tìm thấy tệp.

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

Bây giờ chúng ta hãy xem cách xử lý biến thể Err.

Ví dụ sau xử lý lỗi được trả về khi mở tệp bằng cách sử dụng match tuyên bố

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- Các bản in chương trình kết thúc của chính sự kiện mặc dù tập tin này không được tìm thấy. Điều này có nghĩa là chương trình đã xử lý lỗi một cách khéo léo.

Đầu ra

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

Hình minh họa

Hàm is_even trả về một lỗi nếu số không phải là số chẵn. Hàm main () xử lý lỗi này.

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- Vì hàm main xử lý lỗi một cách khéo léo nên phần cuối của câu lệnh chính được in ra.

Đầu ra

Error msg is NOT_AN_EVEN
end of main

Unrap () và mong đợi ()

Thư viện chuẩn chứa một vài phương thức trợ giúp mà cả hai phương thức enums - Result <T, E> và Option <T> đều thực hiện. Bạn có thể sử dụng chúng để đơn giản hóa các trường hợp lỗi mà bạn thực sự không mong đợi mọi thứ không thành công. Trong trường hợp thành công từ một phương pháp, hàm "unrap" được sử dụng để trích xuất kết quả thực tế.

Sr.No phương pháp Chữ ký & Mô tả
1 mở ra

unwrap(self): T

Tự mong đợi là Ok / Some và trả về giá trị chứa bên trong. Nếu nó làErr hoặc là None thay vào đó, nó gây ra một sự hoảng sợ với nội dung của lỗi được hiển thị.

2 chờ đợi

expect(self, msg: &str): T

Hoạt động giống như mở ra, ngoại trừ việc nó xuất ra một thông báo tùy chỉnh trước khi hoảng sợ cùng với nội dung của lỗi.

mở ()

Hàm unsrap () trả về kết quả thực tế mà một hoạt động thành công. Nó trả về một sự hoảng loạn với thông báo lỗi mặc định nếu một hoạt động không thành công. Hàm này là cách viết tắt của câu lệnh đối sánh. Điều này được hiển thị trong ví dụ dưới đây -

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

Sửa đổi mã trên để chuyển một số lẻ đến is_even() chức năng.

Hàm unsrap () sẽ hoảng loạn và trả về thông báo lỗi mặc định như hình dưới đây

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

chờ đợi()

Chương trình có thể trả về một thông báo lỗi tùy chỉnh trong trường hợp có sự cố. Điều này được thể hiện trong ví dụ sau:

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

Hàm mong đợi () tương tự như hàm unsrap (). Sự khác biệt duy nhất là một thông báo lỗi tùy chỉnh có thể được hiển thị bằng mong đợi.

Đầu ra

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.