۸
مدیریت خطا
روش امن و استاندارد Rust برای مدیریت خطاها با `Result` و `Option`.
خطاهای قابل بازیابی در مقابل غیرقابل بازیابی
Rust خطاها رو به دو دسته تقسیم میکنه:
- خطاهای غیرقابل بازیابی (Unrecoverable): اینا خطاهای خیلی جدی هستن که برنامه نمیتونه ازشون به سلامت عبور کنه. Rust در این مواقع با ماکروی `panic!` برنامه رو متوقف میکنه.
- خطاهای قابل بازیابی (Recoverable): اینا خطاهایی هستن که انتظار داریم اتفاق بیفتن، مثل پیدا نشدن یه فایل. برای این موارد، Rust از `enum` ای به اسم `Result
` استفاده میکنه.
`Result`: موفقیت یا شکست
`Result` یه `enum` هست با دو حالت: `Ok(T)` که مقدار موفقیتآمیز رو نگه میداره، و `Err(E)` که اطلاعات خطا رو نگه میداره. ما با `match` میتونیم هر دو حالت رو مدیریت کنیم.
use std::fs::File;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
}
اپراتور `?`: راه میانبر برای خطاها
نوشتن `match` های تودرتو میتونه خستهکننده باشه. اپراتور `?` یه راه خیلی تمیز برای انتشار (Propagate) خطاهاست. اگه نتیجه یه عملیات `Ok` باشه، مقدار داخلش رو برمیگردونه. اگه `Err` باشه، کل تابع رو متوقف میکنه و اون خطا رو به کسی که تابع رو صدا زده برمیگردونه.
use std::fs::File;
use std::io::{self, Read};
// این تابع یا محتوای فایل رو برمیگردونه یا خطا رو
fn read_username_from_file() -> Result {
let mut f = File::open("hello.txt")?; // اگه خطا بده، از تابع خارج میشه
let mut s = String::new();
f.read_to_string(&mut s)?; // اگه اینجا هم خطا بده، خارج میشه
Ok(s) // اگه همه چی خوب بود، نتیجه موفق رو برمیگردونه
}