
1. Kiểu `Option` – Xử lý giá trị rỗng
Thay vì dùng `null` (thứ gây ra hàng tỷ đô thiệt hại trong lịch sử phần mềm), Rust dùng `Option`. Một biến kiểu `Option` chỉ có thể là:
- `Some(v)`: Chứa một giá trị `v`.
- `None`: Không có giá trị nào cả.
fn get_discount(code: &str) -> Option {
if code == "SUMMER" {
Some(0.2)
} else {
None
}
}
—
2. Kiểu `Result` – Xử lý lỗi thực thi
`Result` dùng cho những thao tác có thể gặp lỗi (ví dụ đọc file, kết nối mạng). Nó gồm:
- `Ok(v)`: Thao tác thành công, trả về giá trị `v`.
- `Err(e)`: Thao tác thất bại, trả về thông tin lỗi `e`.
fn divide(a: f32, b: f32) -> Result {
if b == 0.0 {
Err(String::from("Không thể chia cho 0"))
} else {
Ok(a / b)
}
}
—
3. Cách lấy giá trị ra (Unwrapping)
Để sử dụng giá trị bên trong `Option` hoặc `Result`, bạn nên dùng `match`:
let res = divide(10.0, 2.0);
match res {
Ok(val) => println!("Kết quả: {}", val),
Err(e) => println!("Lỗi: {}", e),
}
Mẹo: Bạn cũng có thể dùng `.unwrap()` nếu chắc chắn 100% là thành công, nhưng hãy cẩn thận: nếu gặp lỗi, chương trình sẽ bị `panic` và dừng ngay lập tức.
—
4. Toán tử dấu chấm hỏi `?`
Đây là “cú pháp ngọt” (syntactic sugar) giúp việc truyền lỗi lên cấp cao hơn trở nên cực kỳ gọn gàng. Nếu kết quả là `Err`, nó sẽ return ngay lập tức khỏi hàm hiện tại.
—
Lời kết Bài 16
Xử lý lỗi trong Rust có thể hơi tốn công lúc đầu, nhưng nó giúp bạn viết ra những ứng dụng cực kỳ ổn định và ít bug. Ở bài sau, chúng ta sẽ tìm hiểu về Generics – bí quyết để viết code linh hoạt cho mọi kiểu dữ liệu.
Hẹn gặp lại các bạn!
Leave a comment