Cú pháp ngắn gọn if let trong Rust
Làm chủ cú pháp if let và if let else trong Rust: tinh gọn mã nguồn, giảm bớt boilerplate so với match khi chỉ cần xử lý một mẫu duy nhất.
Mặc dù match là công cụ mạnh mẽ và an toàn nhờ tính toàn diện (exhaustive), đôi khi bạn chỉ thực sự quan tâm đến duy nhất một trường hợp và muốn bỏ qua tất cả các trường hợp còn lại. Trong tình huống này, việc viết cả một khối match với nhánh _ => () sẽ tạo ra nhiều mã thừa (boilerplate).
Rust cung cấp cú pháp if let như một cách viết ngắn gọn và thanh thoát hơn.
Giải thích đơn giản (ELI5): Chiếc hộp quà may mắn#
Hãy tưởng tượng bạn có một hộp quà bí mật:
- Trong hộp có thể có đồ chơi (
Some(toy)), hoặc chiếc hộp hoàn toàn trống rỗng (None). - Bạn chỉ muốn mở quà nếu có đồ chơi để chơi ngay, còn nếu hộp rỗng thì bạn chẳng cần bận tâm làm gì cả.
graph TD
Input["Giá trị đầu vào (Option / Enum)"] --> Check{"Khớp với mẫu chỉ định không?"}
Check -- Đúng --> Bind["Trích xuất dữ liệu & Chạy khối lệnh if let"]
Check -- Sai --> ElseCheck{"Có khối else không?"}
ElseCheck -- Có --> ElseAction["Chạy khối lệnh else"]
ElseCheck -- Không --> Ignore["Bỏ qua và tiếp tục"]
So sánh: match vs if let#
Giả sử chúng ta chỉ muốn in ra giá trị cấu hình nếu nó tồn tại ở dạng Some(u8):
Cách dùng match (dài dòng)#
let config_max = Some(3u8);
match config_max {
Some(max) => println!("Giá trị tối đa được cấu hình là: {max}"),
_ => (), // Phải thêm nhánh này để thỏa mãn tính toàn diện của match
}rustCách dùng if let (gọn gàng)#
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("Giá trị tối đa được cấu hình là: {max}");
}rust[!TIP] Bạn có thể coi
if letlà cú pháp “đường cú pháp” (syntax sugar) chomatchkhi bạn chỉ thực thi code khi giá trị khớp với một mẫu duy nhất và bỏ qua mọi giá trị khác.
Kết hợp if let với else#
Chúng ta cũng có thể đính kèm một khối else (tương đương với nhánh _ => ... trong biểu thức match):
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
California,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn count_coin(coin: Coin, count: &mut i32) {
if let Coin::Quarter(state) = coin {
println!("Đồng 25 cent từ bang: {state:?}!");
} else {
*count += 1;
}
}
fn main() {
let mut count = 0;
let coin1 = Coin::Quarter(UsState::Alaska);
let coin2 = Coin::Penny;
count_coin(coin1, &mut count);
count_coin(coin2, &mut count);
println!("Số đồng xu khác 25 cent: {count}");
}rustSo sánh: if let vs if thông thường#
Nhiều người mới học Rust thường tự hỏi: Tại sao lại cần if let khi ta đã có câu lệnh if thông thường?
Điểm khác biệt cốt lõi nằm ở khớp mẫu và trích xuất dữ liệu (pattern matching & destructuring):
let score = Some(95);
// 1. Dùng `if` thông thường: chỉ kiểm tra điều kiện Boolean (true/false)
if score.is_some() {
// Phải unwrap thủ công để lấy giá trị ra -> Dễ nhầm lẫn hoặc dài dòng
let val = score.unwrap();
println!("Điểm số: {val}");
}
// 2. Dùng `if let`: vừa kiểm tra mẫu, vừa trích xuất và gán biến ngay lập tức
if let Some(val) = score {
println!("Điểm số: {val}"); // An toàn tuyệt đối, không cần gọi .unwrap()
}rustgraph TD
subgraph IfOrdinary ["if thông thường"]
Cond["Kiểm tra biểu thức Boolean (true/false)"] --> Unsafe["Cần unwrap thủ công nếu muốn lấy dữ liệu bên trong"]
end
subgraph IfLet ["if let"]
Pattern["Khớp mẫu (Pattern Matching)"] --> Safe["Tự động trích xuất dữ liệu & tạo biến cục bộ an toàn"]
end
Khi nào nên dùng if, if let, hay match?#
| Tiêu chí | if thông thường | if let | match |
|---|---|---|---|
| Điều kiện kiểm tra | Biểu thức Boolean (bool) | Mẫu cần khớp (Pattern) | Toàn bộ các mẫu có thể có |
| Trích xuất dữ liệu | Không (phải unwrap thủ công) | Có (tự động bóc tách & gán biến) | Có (bóc tách dữ liệu theo từng nhánh) |
| Tính toàn diện (Exhaustive) | Không | Không (chỉ khớp 1 mẫu) | Có (bắt buộc kiểm tra 100% trường hợp) |
| Số nhánh rẽ | 1 (if) hoặc 2 (if/else) | 1 (if let) hoặc 2 (if let/else) | Bất kỳ số lượng nhánh nào |
| Trường hợp sử dụng tốt nhất | So sánh số, cờ trạng thái logic | Lấy dữ liệu từ Option/Enum với 1 mẫu | Xử lý đa trạng thái phức tạp, máy trạng thái |
[!WARNING] Sử dụng
if letđồng nghĩa với việc bạn từ bỏ sự kiểm tra toàn diện chặt chẽ của trình biên dịch màmatchmang lại. Hãy cân nhắc xem liệu logic bài toán của bạn có nguy cơ bị bỏ sót trường hợp quan trọng nào không.
Tóm tắt#
if letgiúp bạn viết gọn mã nguồn khi chỉ cần kiểm tra một mẫu khớp và trích xuất dữ liệu.- Bạn có thể kết hợp
elseđể xử lý trường hợp không khớp. - Hãy chọn
if letđể loại bỏ mã thừa khi logic chỉ tập trung vào một biến thể duy nhất.