Rust 里的控制流与其他语言没什么差异.
if#
if 的条件不带 (), 条件必须是 bool 类型.
if 是表达式,JS 三元表达式效果直接达成了:
let x = if true { 1 } else { 2 }
循環#
循環控制的 loop 以前沒見過,是無限循環。通過 break 和 continue 控制終止和跳過,Rust 里 break 還能返回值. break,continue 以及循環標籤仨概念在 JS 的 for 里也有,就是 ES6 用習慣了沒怎麼接觸.
標準庫 Range 和 for 配合起來感覺有點意思。寫 JS 循環就想過怎麼沒個控制循環次數的簡潔方案,這下滿足了.
match#
match 類似 JS 里的 switch, 有嚴格檢查確保窮盡了所有可能性。與 [[數據類型 #枚舉]] 配合可以匹配提取枚舉成員包含的值.
let value = match some_value {
Some(i) => i,
None => 0
}
可以使用通配符 (還以為 other 是個關鍵字) 或 other_ 對其他場景做處理,通配符按常理應該寫在最後一個條件,否則會導致其後寫的條件完全無效.
match some_num {
1 => call(),
3 => check(),
other => println!("{}", other),
// 也可以用 _ 不獲取剩餘情況的具體值
// _ => (),
}
if let#
只需處理一種情況的場景,使用 if let 語法更簡潔,但比 match 少了窮盡檢查.
if let Some(value) = some_value {
println!("{}", value);
}
? 運算符#
類似 JS 中的可選鏈, 可作用於 Option 和 Result 傳播錯誤或 None 值。只能寫在返回值兼容的函數體內,比如要對 Result 使用 ? 必須返回 Result. 有一點不同是對 Result 可以在函數體任何位置使用,這樣做會提前中斷並返回 Result::Err.
模式匹配#
模式 是 Rust 中用來匹配類型結構的語法。有點像 JS 的解構賦值, 理解起來有點反邏輯思路,但可使用的場景更多,控制流大部分都能用模式匹配.
let 語句可以模式匹配,= 左側的模式匹配右側表達式,match 分支裡的 => 左側模式匹配 match 關鍵字右側表達式,if let 語句 = 左側模式匹配右側表達式.
let (x, y) = (1, 2);
match some_value {
Some(4) | Some(5) => {},
Some(x) => {},
None => {}
}
if let 1..=3 = some_value {
} else if is_true{
} else {
}
// 解構結構體
let User { name: username, age } = user;
這麼看 if let 有點像 if (模式匹配結果) 句型.
可反駁性#
如果表達式存在不能匹配模式的可能,則這個模式是可反駁的,比如 match 裡的分支條件。反之為不可反駁的模式。也可以說窮盡所有可能性的情況下是不可反駁的. let 和 for 只接受不可反駁模式.
忽略模式中的值#
- 使用
_忽略單個值,可以在一個模式中重複使用; - 使用
..忽略剩餘值,但必須保證被忽略的部分沒有歧義;
匹配守衛#
在 match 的分支條件後可以用 if 關鍵字添加守衛,即額外的匹配條件.
match some_value {
Some(1) | Some(2) => {},
Some(v) if v > 0 => {},
Some(_) => {},
_ => {}
}
添加的 if 作用於前面的整個模式,如果同時使用了 | 運算符指定了多個模式,if 前的優先級更高。以後八成會被這個坑到.
match x {
// 這裡無論 x 是幾都不會匹配
1 | 2 | 3 if false => {},
_ => {}
}
如果希望同時獲取變量並匹配模式,可以使用 @ 綁定.
match user {
// 這裡的 age 被用來匹配了, 後面的塊中無法訪問 age 值
User { age: 1..=18, .. } => {},
// 這樣就可以用了
User { age: user_age @ 20..=35, .. } => {}
}