ข้ามไปยังเนื้อหา

การจัดการข้อผิดพลาด

Rust แบ่งข้อผิดพลาดออกเป็นสองประเภทที่แตกต่างกันโดยพื้นฐาน และจัดการแต่ละประเภทต่างกัน

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

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

ความแตกต่างนี้ถูกบังคับใช้โดยระบบประเภท หากฟังก์ชันล้มเหลวได้แบบที่กู้คืนได้ ประเภทที่คืนค่าของฟังก์ชันนั้นคือ Result<T, E> แต่ถ้าฟังก์ชัน panic ได้ signature จะไม่บอกอะไรคุณเลย — panic เกิดขึ้นได้ทุกที่ แต่ควรสงวนไว้สำหรับบั๊กการเขียนโปรแกรมที่แท้จริง

บทเรียนหัวข้อ
Panicspanic!, .unwrap(), .expect(), เมื่อไหร่ที่การ panic เหมาะสม
ResultResult<T, E>, Ok/Err, การ matching, .unwrap_or, .unwrap_or_else
ตัวดำเนินการ ?การส่งต่อแบบ early-return, การเชื่อมโยง, main ที่คืน Result
ข้อผิดพลาดแบบกำหนดเองenum ข้อผิดพลาด, trait Display + Error, การแปลง From

ตัวอย่างด้านล่างแสดงข้อผิดพลาดทั้งสองประเภทเคียงข้างกัน: panic! ที่คุณจะเรียกเฉพาะเมื่ออินพุตเป็นข้อผิดพลาดทางตรรกะ และฟังก์ชันที่คืนค่า Result ซึ่งผู้เรียกต้องจัดการ

fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("division by zero"))
} else {
Ok(a / b)
}
}
fn main() {
// Recoverable error: use Result
match divide(10, 2) {
Ok(result) => println!("10 / 2 = {}", result),
Err(e) => println!("Error: {}", e),
}
match divide(5, 0) {
Ok(result) => println!("5 / 0 = {}", result),
Err(e) => println!("Error: {}", e),
}
println!("Program continues normally after handling errors.");
}
โครงสร้างใดของ Rust ที่จำลองข้อผิดพลาดที่กู้คืนได้?
panic! ทำอะไรใน Rust?
เหตุใดคอมไพเลอร์ Rust จึงบังคับให้คุณจัดการ Result?