enum Option<T> {
Some(T),
None,
}
有兩個值
一個是Some,另一個則是None
用於表示存在數據或不存在數據
例如初始化、函數返回等
pub enum Result<T, E> {
Ok(T),
Err(E),
}
Result一樣有兩個值
Ok(T)表示操作成功,Err(E)則是操作失敗
用於表示可能成功或失敗的操作
例如文件讀取、網路請求等
獲取值方法
而想要獲得Some或Ok裡面的值
unwrap是一種方法
但unwrap其實有很多種
根據不同場合可以使用不一樣的
有五個我比較常用的
pub fn unwrap(self) -> T
最常用的
直接把Some和Ok的值拿出來
但如果出現None以及Err會直接panic
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.unwrap(), 2);
這樣可以取出2
let x: Result<u32, &str> = Err("emergency failure");
x.unwrap();
如果使用Err,則會panic
panic顯示emergency failure
2. unwrap_or[4]
pub fn unwrap_or(self, default: T) -> T
unwrap_or需要輸入一個預設值
如果發生None或者Err,則以預設值為主
若沒發生則取出Some或Ok
let default = 3;
let ans: Result<i32, &str> = Ok(5);
assert_eq!(ans.unwrap_or(default), 5);
let default = 3;
let ans: Result<i32, &str> = Err("error");
assert_eq!(ans.unwrap_or(default), 3);
第一次unwrap_or,成功
所以取出的值是5
第二次unwrap_or,失敗
但有輸入預設值,當失敗值會輸出預設值,也就是3
3. unwrap_or_else[5]
pub fn unwrap_or_else<F>(self, op: F) -> T
unwrap_or_else,需要輸入一個閉包
要馬回傳Some或Ok,要馬會回傳閉包值
fn get_user_info(user_id: u32) -> Result<&'static str, &'static str> {
match user_id {
1 => Ok("User: Alice"),
2 => Ok("User: Bob"),
_ => Err("User not found"),
}
}
fn main() {
let user_id_to_fetch = 2;
let user_info = get_user_info(user_id_to_fetch);
let result = user_info.unwrap_or_else(|err| {
println!("Error retrieving user info: {}", err);
"Unknown User"
});
println!("User Info: {}", result);
}
User Info: User: Bob一個例子,透過unwrap_or_else可以處理Err的情況
如果沒有Err,則會回傳正確的值
以範例程式來說,就是回傳人物的名字
如果Err,則會執行閉包內容,閉包元素為Err錯誤訊息
舉個錯誤例子
fn get_user_info(user_id: u32) -> Result<&'static str, &'static str> {
match user_id {
1 => Ok("User: Alice"),
2 => Ok("User: Bob"),
_ => Err("User not found"),
}
}
fn main() {
let user_id_to_fetch = 5;
let user_info = get_user_info(user_id_to_fetch);
let result = user_info.unwrap_or_else(|err| {
println!("Error retrieving user info: {}", err);
"Unknown User"
});
println!("User Info: {}", result);
}
Error retrieving user info: User not found
User Info: Unknown User會先將err訊息列印出來,然後把Unknown User放入result
最後再次印出來
4. unwrap_or_default[6]
pub fn unwrap_or_default(self) -> T
unwrap_or_default,跟unwrap_or很像
但unwrap_or需要輸入預設值
unwrap_or_default則不需要
會回傳類型的默認值
例如
let num: Result<i32, i32> = Ok(3);
let num1: Result<i32, i32> = Err(1);
println!("success: {}", num.unwrap_or_default());
println!("error: {}", num1.unwrap_or_default());
success: 3
error: 0
如果是Ok,則直接回傳Ok值
而如果是Err,則回傳型態默認值
i32的默認值是0
因此最後會回傳0
5. unwrap_err[7]
pub fn unwrap_err(self) -> E
跟上方四個不一樣
這個是要回傳錯誤的值
如果是Ok會panic
例如
fn main() {
let num: Result<i32, &str> = Err("Something wrong");
println!("error: {}", num.unwrap_err());
}
error: Something wrong
但如果是這樣
let num: Result<i32, &str> = Ok(666);
println!("Ok: {}", num.unwrap_err());
thread 'main' panicked at 'called `Result::unwrap_err()` on an `Ok` value: 666'
Ok反而會直接跳出錯誤訊息
參考資料
[1] https://doc.rust-lang.org/std/option/enum.Option.html
[2] https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
[3] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap
[4] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or
[5] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else
[6] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_default
[7] https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_err