条件分支结构
if
结构:
if condition {
} else if condition {
} else {
}
fn main() { let number = 6; if number % 4 == 0 { println!("number is divisible by 4"); } else if number % 3 == 0 { println!("number is divisible by 3"); } else if number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } }Rust 中 if 结构的 condition 必须是一个 bool 类型(与 Python 不同)。
fn main() { let number = 3; if number { println!("number was three"); } }Rust 的 if 是一个表达式,可以用做赋值操作,以最后一个没有分号的表达式作为值返回,一个if 结构只会产生一个值。
fn main() { let condition = true; let number = if condition { 100 } else { 2 }; println!("The value of number is: {number}"); }每个if 结构的所有分支的返回类型必须相同。
fn main() { let condition = true; let number = if condition { 100 } else { "x" }; println!("The value of number is: {number}"); }没有显式返回时,返回类型为元组()。
fn main() { let condition = true; let number = if condition { 100 } else { }; }match
基本结构
match 值 {
模式1 => 表达式1,
模式2 => 表达式2,
_ => 默认表达式,
}
enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }Rust 要求 match 的分支必须穷举被匹配对象所有可能的值(Matches Are Exhaustive)来提高安全性,防止开发者遗漏。
Rust 使用 _ 占位符表示剩余情况。
fn main() { let dice_roll = 9; match dice_roll { 3 => println!("3"), 7 => println!("7"), _ => println!("no dice roll"), } }if let
match 语法是穷举的,所以如果你仅只想匹配一种模式,也要使用 _。
fn main() { let config_max = Some(3u8); match config_max { Some(max) => println!("The maximum is configured to be {max}"), _ => (), } }这就显得很臃肿了,为此,Rust 提供了if let 语法,上面的代码等价于:
fn main() { let config_max = Some(3u8); if let Some(max) = config_max { println!("The maximum is configured to be {max}"); } }注意:if let 只能用于模式匹配,不能用于 先赋值 再做bool 判断(与 Python 不同),比如:
fn main() { let c = [1, 2, 3, 4, 5]; if let a = c[0] == 2 { println!("hello,world!"); } }猜猜会输出什么?
了解过python的读者可能会这么理解这个条件:
- 先把c[0] 赋值给变量a
- 判断a是否等于2
- 由于c[0] 等于1,所以条件为假,不执行打印语句。
看下结果:
【hello,world!】居然输出出来了。这恰恰证明了Rust不支持像Python语言的海象操作符那样的运算。
实际上逻辑是这样的,
if let后面写的是模式匹配,a是一个“总能匹配成功”的变量模式,所以它本身没有筛选条件。
真正执行到这里时:
c[0] == 2会先被计算成一个布尔值- 结果是
false - 然后
false也能被a这个模式匹配上 - 所以
if代码块一定会执行
所以:
- 表面上看像条件:
c[0] == 2 - 实际上的条件:没有条件,
if let a = ...这种写法基本等价于“把右边的值绑定给 a,然后进入代码块”,代码块中的代码会无条件执行!!
循环结构
break
跳出某个循环(默认跳出 break 所在的循环)
continue
跳过本轮,进入下一轮
loop
Rust 设计了 loop 关键字(很有古韵)。
fn main() { loop { println!("again!"); } }Rust 的 loop 是一个expression 可以返回值。
fn main() { let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; println!("The result is {result}"); }while
while 实际上就是 loop ,if,和break搭配使用的结果。
fn main() { let mut number = 3; while number != 0 { println!("{number}!"); number -= 1; } println!("LIFTOFF!!!"); }等价于:
fn main() { let mut number = 3; loop { if number == 0 { break; } println!("{number}!"); number -= 1; } println!("LIFTOFF!!!"); }for
Rust 没有C/Java/Go风格的for循环遍历,均是迭代器循环。
for 模式 in 迭代器 {
循环体
}
基本用法:
fn main() { // 左闭右开 // 正序 for i in 0..10 { println!("{}",i); } // 倒序 for i in (0..10).rev() { println!("{}",i); } }loop labels
Rust 的三种循环loop、while、for都可以使用循环标签(label),而且标签语法完全一致。
'label: loop { ... }
'label: while cond { ... }
'label: for x in iter { ... }
可以搭配 break 实现跳出指定循环的效果。
fn main() { let mut count = 0; 'counting_up: loop { println!("count = {count}"); let mut remaining = 10; loop { println!("remaining = {remaining}"); if remaining == 9 { break; } if count == 2 { break 'counting_up; } remaining -= 1; } count += 1; } println!("End count = {count}"); }