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