Toán tử dấu hỏi này về cái gì?


Câu trả lời:


144

Như bạn có thể nhận thấy, Rust không có ngoại lệ. Nó gây hoảng loạn, nhưng chức năng của chúng bị hạn chế (chúng không thể mang thông tin có cấu trúc) và việc sử dụng chúng để xử lý lỗi không được khuyến khích (chúng dành cho các lỗi không thể khôi phục).

Trong Rust, xử lý lỗi sử dụng Result. Một ví dụ điển hình sẽ là:

fn halves_if_even(i: i32) -> Result<i32, Error> {
    if i % 2 == 0 {
        Ok(i / 2)
    } else {
        Err(/* something */)
    }
}

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = match halves_if_even(i) {
        Ok(i) => i,
        Err(e) => return Err(e),
    };

    // use `i`
}

Điều này thật tuyệt vì:

  • khi viết mã, bạn không thể vô tình quên xử lý lỗi,
  • khi đọc mã bạn có thể thấy ngay rằng có khả năng xảy ra lỗi ngay tại đây.

Tuy nhiên, nó ít lý tưởng hơn ở chỗ nó rất dài dòng. Đây là lúc toán tử dấu hỏi ?đi vào.

Phần trên có thể được viết lại thành:

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = halves_if_even(i)?;

    // use `i`
}

ngắn gọn hơn nhiều.

Điều gì ?ở đây tương đương với matchcâu lệnh trên. Tóm lại: nó giải nén Resultnếu OK và trả về lỗi nếu không.

Nó hơi kỳ diệu một chút, nhưng việc xử lý lỗi cần một số phép thuật để cắt bớt bảng soạn sẵn, và không giống như các trường hợp ngoại lệ, nó có thể nhìn thấy ngay lập tức lệnh gọi hàm nào có thể xảy ra hoặc không thể xảy ra lỗi: những lệnh được tô điểm bằng ?.

Một ví dụ về điều kỳ diệu là điều này cũng hoạt động cho Option:

// Assume
// fn halves_if_even(i: i32) -> Option<i32>

fn do_the_thing(i: i32) -> Option<i32> {
    let i = halves_if_even(i)?;

    // use `i`
}

Điều này được hỗ trợ bởi Tryđặc điểm (không ổn định) .

Xem thêm:


5
sẽ rất tuyệt nếu bạn có thể mở rộng câu trả lời của mình một chút, chẳng hạn như thảo luận rằng kiểu trả về của hàm phải khớp với kiểu bạn cố gắng "mở", ví dụ: Resulthoặc Option.
hellow

@hellow Tôi đoán đó tốt hơn là một câu hỏi mới hoàn toàn
Paul Razvan Berg

2

Nó dùng để truyền lỗi cho loại lỗi có thể khôi phục được. Kết quả <T, E>. Nó mở ra kết quả và cung cấp cho bạn giá trị bên trong.

Thay vì xử lý trường hợp lỗi, bạn truyền nó tới mã người gọi và chỉ xử lý trường hợp Ok. Lợi ích là, nó loại bỏ rất nhiều bảng soạn sẵn và làm cho việc thực hiện chức năng đơn giản hơn.


không bị nhầm lẫn với thực tế .unwrap()mà hoảng sợ trong trường hợp có lỗi.
Jordan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.