สนิม - การจัดการข้อผิดพลาด

ใน Rust ข้อผิดพลาดสามารถแบ่งออกเป็นสองประเภทใหญ่ ๆ ดังแสดงในตารางด้านล่าง

ซีเนียร์ No ชื่อและคำอธิบาย การใช้งาน
1

Recoverable

ข้อผิดพลาดที่สามารถจัดการได้

ผลลัพธ์ enum
2

UnRecoverable

ข้อผิดพลาดที่ไม่สามารถจัดการได้

มาโครตื่นตระหนก

ข้อผิดพลาดที่สามารถกู้คืนได้คือข้อผิดพลาดที่สามารถแก้ไขได้ โปรแกรมสามารถลองดำเนินการที่ล้มเหลวอีกครั้งหรือระบุแนวทางการดำเนินการอื่นเมื่อพบข้อผิดพลาดที่สามารถกู้คืนได้ ข้อผิดพลาดที่สามารถกู้คืนได้ไม่ทำให้โปรแกรมล้มเหลวในทันที ตัวอย่างของข้อผิดพลาดที่คาดว่าจะไม่พบไฟล์ข้อผิดพลาด

ข้อผิดพลาดที่ไม่สามารถกู้คืนได้ทำให้โปรแกรมล้มเหลวทันที โปรแกรมไม่สามารถเปลี่ยนกลับสู่สถานะปกติได้หากเกิดข้อผิดพลาดที่ไม่สามารถกู้คืนได้ ไม่สามารถลองอีกครั้งการดำเนินการที่ล้มเหลวหรือยกเลิกข้อผิดพลาด ตัวอย่างของข้อผิดพลาดที่ไม่สามารถกู้คืนได้พยายามเข้าถึงตำแหน่งที่อยู่นอกเหนือจากจุดสิ้นสุดของอาร์เรย์

ไม่เหมือนกับภาษาโปรแกรมอื่น ๆ Rust ไม่มีข้อยกเว้น จะส่งคืน enum Result <T, E>สำหรับข้อผิดพลาดที่สามารถกู้คืนได้ในขณะที่มันเรียกpanicแมโครหากโปรแกรมพบข้อผิดพลาดที่ไม่สามารถกู้คืนได้ ตื่นตระหนกแมโครทำให้โปรแกรมเพื่อออกทันที

Panic Macro และข้อผิดพลาดที่ไม่สามารถกู้คืนได้

ตื่นตกใจ! มาโครช่วยให้โปรแกรมยุติทันทีและให้ข้อเสนอแนะแก่ผู้เรียกโปรแกรม ควรใช้เมื่อโปรแกรมถึงสถานะที่ไม่สามารถกู้คืนได้

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.

โปรแกรมสามารถทำให้ตื่นตระหนก! macro หากละเมิดกฎทางธุรกิจดังที่แสดงในตัวอย่างด้านล่าง -

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 และข้อผิดพลาดที่กู้คืนได้

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 (File)หากไฟล์มีอยู่แล้วและErr (Error)หากไม่พบไฟล์

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

NOTE- โปรแกรมพิมพ์จุดสิ้นสุดของเหตุการณ์หลักแม้ว่าจะไม่พบไฟล์ ซึ่งหมายความว่าโปรแกรมได้จัดการข้อผิดพลาดอย่างสง่างาม

เอาต์พุต

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

NOTE- เนื่องจากฟังก์ชั่นหลักจัดการกับข้อผิดพลาดอย่างสง่างามส่วนท้ายของคำสั่งหลักจึงถูกพิมพ์ออกมา

เอาต์พุต

Error msg is NOT_AN_EVEN
end of main

แกะ () และคาดหวัง ()

ไลบรารีมาตรฐานมีตัวช่วยสองสามวิธีที่ทั้งสอง enums - ผลลัพธ์<T, E>และตัวเลือก<T>นำไปใช้ คุณสามารถใช้เพื่อลดความซับซ้อนของกรณีข้อผิดพลาดโดยที่คุณไม่คาดหวังว่าสิ่งต่างๆจะล้มเหลว ในกรณีที่ประสบความสำเร็จจากวิธีการหนึ่งฟังก์ชัน "แกะ" จะถูกใช้เพื่อดึงผลลัพธ์ที่แท้จริงออกมา

ซีเนียร์ No วิธี ลายเซ็นและคำอธิบาย
1 แกะ

unwrap(self): T

คาดหวังให้ตัวเองเป็น Ok / Some และส่งคืนค่าที่อยู่ภายใน ถ้ามันเป็นErr หรือ None แต่กลับสร้างความตื่นตระหนกกับเนื้อหาของข้อผิดพลาดที่ปรากฏขึ้น

2 คาดหวัง

expect(self, msg: &str): T

ทำตัวเหมือนแกะออกยกเว้นว่าจะส่งออกข้อความที่กำหนดเองก่อนที่จะตื่นตระหนกนอกเหนือไปจากเนื้อหาของข้อผิดพลาด

แกะ()

ฟังก์ชันแกะ () ส่งคืนผลลัพธ์จริงที่การดำเนินการสำเร็จ ส่งคืนความตื่นตระหนกพร้อมข้อความแสดงข้อผิดพลาดเริ่มต้นหากการดำเนินการล้มเหลว ฟังก์ชันนี้เป็นชวเลขสำหรับคำสั่งจับคู่ สิ่งนี้แสดงในตัวอย่างด้านล่าง -

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() ฟังก์ชัน

ฟังก์ชันแกะ ()จะตื่นตระหนกและส่งกลับข้อความแสดงข้อผิดพลาดเริ่มต้นดังที่แสดงด้านล่าง

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

ฟังก์ชัน expect () คล้ายกับการแกะ () ข้อแตกต่างเพียงอย่างเดียวคือข้อความแสดงข้อผิดพลาดที่กำหนดเองสามารถแสดงได้โดยใช้การคาดหวัง

เอาต์พุต

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.