[Rust] Tìm hiểu về enum std::Result
Hôm nay chúng ta sẽ tìm hiểu về std::Result - Một enum thường được được sử dụng để biểu thị 1 giá trị Ok(T)
hoặc là một giá trị Err(E)
pub enum Result<T,E> {
Ok(T),
Err(E),
}
Ý nghĩa: Giá trị có thể là kiểu T
hoặc là một lỗi dạng E
. Ví dụ một hàm thành công trả về Ok(T)
hoặc trả về một lỗi thể hiện Err(E)
Initalization - Khởi tạo
Đầu tiên để khởi tạo ra Result<T, E>
cách đơn giản là wrap nó vào Some như định nghĩa của nó
fn test_option_return_ok() -> Result<u32, String> {
Ok(100) // return 100
}
// Vì lỗi là String chỉ cần wrap nó trong Err
fn test_option_return_error() -> Result<u32, String> {
Err(String::from("trả về lỗi"))
}
Methods
Chúng ta sẽ điểm lại một số function quan trọng hay sử dụng
Các hàm kiểm tra
is_err
let x: Result<i32, &str> = Ok(-3);
assert_eq!(x.is_err(), false);
let x: Result<i32, &str> = Err("Some error message");
assert_eq!(x.is_err(), true);
Ý nghĩa: Hàm này kiểm tra một biến có phải err hay không
is_ok
pub const fn is_ok(&self) -> bool
let x: Result<i32, &str> = Ok(-3);
assert_eq!(x.is_ok(), true);
let x: Result<i32, &str> = Err("Some error message");
assert_eq!(x.is_ok(), false);
Hàm với panic
unwrap
pub fn unwrap(self) -> T
where
E: Debug,
// Khởi tạo giá trị là Ok(2)
let x: Result<u32, &str> = Ok(2);
// Vì là Ok
assert_eq!(x.unwrap(), 2);
Ý nghĩa: Hàm này sẽ panic nếu như trong trường hợp Result
là một kiểu Err
unwrap_or_default
pub fn unwrap_or_default(self) -> T
where
T: Default,
Ý nghĩa: Nếu gặp lỗi chúng ta sẽ trả về giá trị mặc định
let good_year_from_input = "1909";
let bad_year_from_input = "190blarg";
// parse trở về Ok nên sẽ không trả về mặc định
let good_year = good_year_from_input.parse().unwrap_or_default();
// Gặp lỗi cà trả về mặc định của kiểu u32 là 0
let bad_year = bad_year_from_input.parse().unwrap_or_default();
assert_eq!(1909, good_year);
assert_eq!(0, bad_year);
Các hàm với map
map
pub fn map_err<F, O>(self, op: O) -> Result<T, F>
where
O: FnOnce(E) -> F,
Ý nghĩa:
Hàm này sẽ biến đổi kiểu lỗi Err(O)
tới kiểu Err(F)
Hàm này khá quan trọng vì hay được sử dụng. Ví dụ hàm main của chúng ta trả về
fn main() -> Result<(), sqlx::Error>{}
Giả sử trong hàm này chúng ta có đoạn cần kết nối tới mongo và trả về lỗi
connect(&mongo_url).await // --> Kiểu trả lỗi lại là Err(mongo::ConnectionRefused)
// Lúc này ta cần biến đối nó thành sqlx::Error
// trong đó e là dạng Err(mongo::ConnectionRefused)
connection(&mongo_url).await.map_err(|e| Error(sqlx::Error))
Thủ thuật này thường xuyên được sử dụng