星期六, 11月 18, 2023

Rust 的基礎 - Option

在日常的程式開發中,有一種意外中止的情況:對 Null Pointer 進行了 Dereference。在 Java 中會丟出 Null Pointer Exception,在 C/C++ 則是觸發 Segmentation Fault。

那麼在 Rust 當中呢?

我們來看以下的範例

fn get_bigger<'a>(s1: &'a String, s2: &'a String) -> Option<&'a String> {
   if s1.len() > s2.len() {
      return Some(s1);
   } else if s1.len() < s2.len() {
      return Some(s2);
   } else {
      return None;
   }  
}
在這個範例中
  1. 定義了一個 get_bigger function
  2. 接受兩個 Reference
  3. 回傳 Option<&String>
    • 回傳較長字串的 Reference
    • 若一樣長,回傳 None

如果想要取得較長字串的長度

fn main() {
   let buf1 = "Hello".to_string();
   let buf2 = "World".to_string();

   let bigger = get_bigger(&buf1, &buf2);

   println!("{}", bigger.len());
}
會得到編譯錯誤
println!("{}", bigger.len());
                      ^^ method not found in `Option<&String>`
如果想要取得回傳的長度,必須對 Option 作拆封的動作
   if let Some(value) = bigger {
      println!("The bigger {}", value);
   } else {
      println!("Same");
   }

在使用 Option 的時候由於強制拆封,以此避免了對 None 進行操作的可能性。在以後的 Code 我們陸續可以看到這種強制拆封避免了開發者對不正常的值作操作的可能。

以下是完整的 Code

fn get_bigger<'a>(s1: &'a String, s2: &'a String) -> Option<&'a String> {
   if s1.len() > s2.len() {
      return Some(s1);
   } else if s1.len() < s2.len() {
      return Some(s2);
   } else {
      return None;
   }  
}

fn main() {
   let buf1 = "Hello".to_string();
   let buf2 = "World".to_string();

   let bigger = get_bigger(&buf1, &buf2);

   if let Some(value) = bigger {
      println!("The bigger {}", value);
   } else {
      println!("Same");
   }
}

沒有留言: