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

Panics และ Unwrap

Panic คือวิธีที่ Rust บอกว่า “สถานการณ์นี้คือบั๊ก — ฉันไม่สามารถดำเนินการต่อได้อย่างปลอดภัย” เมื่อ panic เกิดขึ้น Rust จะคลายสแต็กการเรียก รัน destructor และยุติเธรดปัจจุบัน ในโปรแกรมแบบ single-thread หมายความว่าโปรเซสทั้งหมดจะออก

คุณสามารถทริกเกอร์ panic อย่างชัดเจนด้วย macro panic!:

fn main() {
panic!("something went terribly wrong");
}

หลายการดำเนินการมาตรฐานยัง panic โดยอัตโนมัติเมื่อใช้ไม่ถูกต้อง:

fn main() {
let v = vec![1, 2, 3];
println!("{}", v[10]); // index out of bounds — panic!
}
fn main() {
let x: Option<i32> = None;
let _ = x.unwrap(); // called unwrap() on a None value — panic!
}

.unwrap() บน Option<T> หรือ Result<T, E> ดึงค่าภายในหากเป็น Some/Ok และpanic หากเป็น None/Err เป็นทางลัดที่แลกความปลอดภัยกับความกระชับ

.expect(msg) ทำสิ่งเดียวกัน แต่ให้คุณกำหนดข้อความอธิบายที่ปรากฏในผลลัพธ์ panic ทำให้การ debug ง่ายขึ้นมาก

fn main() {
let some_value: Option<i32> = Some(42);
let n = some_value.unwrap(); // fine — value is Some
println!("n = {}", n);
let parsed: Result<i32, _> = "99".parse();
let m = parsed.expect("input should always be a valid integer");
println!("m = {}", m);
}

Panic เหมาะสมเมื่อ:

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

Panic ไม่เหมาะสมเมื่อ:

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

ค่าเริ่มต้นที่ปลอดภัยกว่าด้วย .unwrap_or และ .unwrap_or_else

หัวข้อที่มีชื่อว่า “ค่าเริ่มต้นที่ปลอดภัยกว่าด้วย .unwrap_or และ .unwrap_or_else”

เมื่อคุณต้องการค่าสำรองแทนการ panic ให้ใช้ .unwrap_or(default) หรือ .unwrap_or_else(|| compute_default())

fn safe_sqrt(n: f64) -> Result<f64, String> {
if n < 0.0 {
Err(format!("cannot take sqrt of negative number: {}", n))
} else {
Ok(n.sqrt())
}
}
fn main() {
// .unwrap_or provides a default instead of panicking
let a: Option<i32> = Some(42);
let b: Option<i32> = None;
println!("a unwrap_or: {}", a.unwrap_or(0));
println!("b unwrap_or: {}", b.unwrap_or(0));
// .expect gives a custom panic message (use only when failure is a bug)
let good = safe_sqrt(16.0).expect("sqrt should not fail on positive numbers");
println!("sqrt(16) = {}", good);
// .unwrap_or_else with a closure for recoverable defaults
let result = safe_sqrt(-4.0).unwrap_or_else(|e| {
println!("Handled: {}", e);
0.0
});
println!("result = {}", result);
}
อะไรเกิดขึ้นเมื่อคุณเรียก .unwrap() บนค่า None?
ความแตกต่างระหว่าง .unwrap() และ .expect(msg) คืออะไร?
สถานการณ์ใดที่เป็นการใช้ panic! ที่ถูกต้อง?
.unwrap_or(default) ทำอะไรเมื่อ Option เป็น None?