Result
Result
là phiên bản nâng cấp của kiểu Option
, mô tả lỗi có thể xảy ra thay vì chỉ mô tả việc kết quả có thể có hoặc không có.
Đúng với nhận định trên, Result<T, E>
trong Rust có thể có một trong hai kết quả:
Ok(T)
: Một thực thểT
được tìm thấyErr(E)
: Một lỗi được tìm thấy làE
Trong Rust, quy ước rằng kết quả mong đợi của một hàm là Ok
, trong khi kết quả không mong đợi là Err
.
Tương tự Option
, Result
đi kèm với rất nhiều phương thức. Ví dụ như unwrap()
,
sẽ trả về thực thể T
hoặc panic
. Tùy vấn đề cần xử lí mà ta kết hợp cả Result
và Option
.
Khi dùng Rust, bạn sẽ thường gặp các phương thức trả về kiểu dữ liệu Result
,
như là phương thức parse()
. Không phải lúc nào cũng có thể chuyển đổi
một chuỗi kí tự thành một kiểu dữ liệu khác nên parse()
sẽ trả về một
kiểu dữ liệu Result
cho biết có thể lỗi sẽ xảy ra.
Hãy xem xét những gì sẽ xảy ra khi chúng ta chuyển đổi thành công và không thành công một chuỗi bằng phương thức parse()
:
fn multiply(first_number_str: &str, second_number_str: &str) -> i32 { // Let's try using `unwrap()` to get the number out. Will it bite us? let first_number = first_number_str.parse::<i32>().unwrap(); let second_number = second_number_str.parse::<i32>().unwrap(); first_number * second_number } fn main() { let twenty = multiply("10", "2"); println!("double is {}", twenty); let tt = multiply("t", "2"); println!("double is {}", tt); }
Trong trường hợp không thành công, phương thức parse()
sẽ gây ra lỗi panic
. Ngoài ra, lỗi panic
cũng sẽ kết thúc chương trình và cung cấp một thông báo lỗi không mong muốn.
Để cải thiện chất lượng thông báo lỗi, chúng ta nên cụ thể hóa hơn về kiểu giá trị trả về và xử lí lỗi kĩ càng hơn
Using Result
in main
Kiểu dữ liệu Result
cũng có thể là kiểu dữ liệu trả về của hàm main
nếu được chỉ định rõ ràng. Thông thường, hàm main
sẽ có dạng:
fn main() { println!("Hello World!"); }
Tuy nhiên hàm main
cũng trả về kiểu Result
. Nếu một lỗi xảy ra trong hàm main
,
nó sẽ trả về mã lỗi và in ra một bản trình bày về lỗi (sử dụng trait Debug
).
Ví dụ sau đây là một trường hợp minh chứng và đề cập đến các khía cạnh được
nói qua ở [mục này].
use std::num::ParseIntError; fn main() -> Result<(), ParseIntError> { let number_str = "10"; let number = match number_str.parse::<i32>() { Ok(number) => number, Err(e) => return Err(e), }; println!("{}", number); Ok(()) }