Chuyển đến nội dung chính
Mô-đun 2 · Bài học 2 trong tổng số 24/14 trong khóa học~15 min
Bài học theo mô-đun (2/2)

Khớp mẫu, tùy chọn và kết quả

Rust có một cơ chế luồng điều khiển cực kỳ mạnh mẽ được gọi là khớp mẫu. Nó cho phép bạn so sánh một giá trị với một loạt mẫu và thực thi mã dựa trên mẫu nào khớp.

Tuyên bố match

Câu lệnh match trong Rust tương tự như switch trong các ngôn ngữ khác nhưng mạnh mẽ và an toàn hơn nhiều. Trình biên dịch đảm bảo rằng kết quả khớp là đầy đủ, nghĩa là tất cả các trường hợp có thể xảy ra đều phải được xử lý:

Rust
enum Direction {
    North,
    South,
    East,
    West,
}

let dir = Direction::East;

match dir {
    Direction::North => println!("Andiamo a Nord"),
    Direction::South => println!("Andiamo a Sud"),
    Direction::East => println!("Andiamo a Est"),
    Direction::West => println!("Andiamo a Ovest"),
}

Xử lý sự vắng mặt của giá trị: Option

Rust không có khái niệm về giá trị null (null hoặc nil). Thay vào đó, thư viện chuẩn định nghĩa một enum có tên Option<T> có thể chứa:

  • Some(T): chứa giá trị thuộc loại T.
  • None: biểu thị thiếu giá trị.
Rust
let x: Option<i32> = Some(5);
let y: Option<i32> = None;

match x {
    Some(val) => println!("C'e un valore: {}", val),
    None => println!("Nessun valore trovato"),
}

Xử lý lỗi có thể phục hồi: Result

Đối với các thao tác có thể thất bại (như đọc tệp hoặc phân tích chuỗi thành số), Rust sử dụng enum Result<T, E>, có hai biến thể:

  • Ok(T): thao tác thành công và chứa giá trị thành công T.
  • Err(E): thao tác không thành công và có lỗi E.
Rust
fn divide(numerator: f64, denominator: f64) -> Result<f64, String> {
    if denominator == 0.0 {
        Err(String::from("Divisione per zero!"))
    } else {
        Ok(numerator / denominator)
    }
}

Nhờ trình biên dịch của Rust, bạn buộc phải xử lý trường hợp Err trước khi có thể truy cập giá trị bên trong Ok, ngăn ngừa nhiều lỗi thời gian chạy phổ biến.

Mẫu ký tự đại diện _

Khi làm việc với các loại dữ liệu có số lượng biến thể lớn (như số nguyên), việc liệt kê tất cả các trường hợp trong match là không thể. Rust cho phép sử dụng ký tự đại diện _ để bắt tất cả các trường hợp còn lại không được xác định rõ ràng:

Rust
let some_u8 = 3u8;
match some_u8 {
    1 => println!("One"),
    2 => println!("Two"),
    _ => println!("Something else"), // Handles all other values
}

Hãy tự mình thử

tập thể dục#rust.m2.l2.e1
Nỗ lực: 0Đang tải…

Khai báo một biến có tên may_value thuộc loại Option<i32> chứa Some(42). Sử dụng câu lệnh so khớp trên Maybe_value: nếu nó chứa Some(v) print 'value is: v' (sử dụng println!), nếu nó chứa None print 'no value'.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Viết một khối `match may_value { Some(v) => println!('value is: {}', v), None => println!('no value') }`.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#rust.m2.l2.e2
Nỗ lực: 0Đang tải…

Hoàn thành hàm check_age để nó trả về Ok('Adult') nếu tuổi lớn hơn hoặc bằng 18 và Err('Minor') nếu ngược lại.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Sử dụng `if age >= 18`để quyết định xem nên return`Ok('Adult')` hay`Err('Minor')`.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#rust.m2.l2.e3
Nỗ lực: 0Đang tải…

Khai báo một enum có tên Trạng thái chứa các biến thể Hoạt động và Không hoạt động. Trong main, khai báo biến current_status với giá trị Status::Active. Cuối cùng, sử dụng câu lệnh so khớp trên current_status để in 'active' nếu trạng thái là Đang hoạt động hoặc 'không hoạt động' nếu trạng thái là Không hoạt động.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Xác định enum trước main bằng `enum Status { Active, Inactive }`. Trong main, sử dụng `let current_status = Status::Active;`và thực hiện`match` trên các biến thể.

Giải pháp khả dụng sau 3 lần thử