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, .. } => {}
}