模式比對與窮盡性(pattern matching and match)
你已經見過 Option 與 Result,它們把一個值裝在幾種形狀之一裡——Some 或 None、Ok 或 Err。要使用它們,你需要一種辦法去問「它是哪種形狀」,並把裡頭的東西取出來。C 的 switch 處理一個數字或單一字元,而若你忘了 break 還會貫穿下去;它無法看進一個結構化的值裡,也無法保證你涵蓋了每種情形。Rust 的答案是 match 運算式:你列出值可能呈現的每種形狀,並為每一種寫下要做什麼,常常在同一口氣裡把內部資料綁定到一個名字上。
match 取一個值,依序試每個模式直到有一個吻合,然後執行那個分支。模式可以一次做兩件事:它測試形狀,並把它拆解開、替裡頭的部件命名。寫 match opt { Some(x) => ..., None => ... } 會檢查 opt 是不是 Some,若是,就把所裝的值綁定到 x,好讓你在那個分支裡使用它——不必分兩步「先問是不是 Some、再讀裡頭」。模式能巢狀與組合:你可以對特定值、對範圍、對結構的欄位做比對,用 x | y 一次比對多個選項,並加一個寫作 _ 的最後萬用分支來涵蓋你沒有明確點名的一切。
讓 match 不只是個整潔 switch 的,是窮盡性:編譯器檢查你的模式涵蓋了每一種可能情形,若漏掉哪怕一種,它就以「模式不窮盡」拒絕編譯。這悄悄地很有力。它意味著你永遠不可能忘記處理 None、或 Err、或一個新加的變體——當有人替某個型別加上第三種形狀的那天,每個沒有顧及它的 match 都會停止編譯,正好把你指向現在需要更新的那段程式碼。為何重要:窮盡性把一整類「漏了某種情形」的錯誤(C switch 裡少掉的 default、沒處理的錯誤路徑)從一個無聲的執行期驚嚇,變成一張編譯器陪你逐項走過的編譯期檢查清單。
let n: Option<i32> = Some(3); let msg = match n { Some(0) => "零".to_string(), Some(x) if x < 0 => format!("負的 {x}"), Some(x) => format!("正的 {x}"), None => "沒有".to_string(), }; // 漏掉 None 會失敗:模式不窮盡
match 一步完成測試與拆解;編譯器堅持每種情形都被涵蓋。
窮盡性才是安全上的收穫,而不只是漂亮語法:漏一種情形程式就無法編譯。_ 分支是一個刻意的萬用項——要有意地用它,而不是用來消掉你其實想要的窮盡性檢查。