前言
这是 【🔥前端学rust】 系列文章的第五篇文章了。其他内容如下:
这篇文章我们学习 rust
中的流程控制。rust
是一种注重安全性和并发性的系统编程语言,提供了多种流程控制语句,包括条件语句 (if
, else
, match
)、循环语句 (loop
, while
, for
)、模式匹配语句 (if let
和 while let
) 以及其他控制流语句 (continue
, break
, return
)。
条件语句
if/else
rust
中的 if 语句和大多数语言类似,用于基于条件执行代码。if
语句用于执行满足条件的代码块。else
部分则是当条件不满足时执行的代码块。不同的是,rust
语言中的布尔判断条件不必使用小括号包裹,且每个条件后面都跟着一个代码块。if
-else
条件选择是一个表达式,并且所有分支都必须返回相同的类型。
n main() {
let number = 5;
if number < 10 {
println!("The number is less than 10");
} else if number == 10 {
println!("The number is exactly 10");
} else {
println!("The number is greater than 10");
}
}
需要注意的是 rust
的 if
是一种表达式,可以返回值。可以实现三元表达式的效果。
fn main() {
let number = 5;
let message = if number < 10 {
"The number is less than 10"
} else {
"The number is greater than or equal to 10"
};
// ^ 不要忘记在这里加上一个分号!所有的 `let` 绑定都需要它。
println!("{}", message);
}
match
match
语句用于多分支的选择,类似于 JavaScript
中的 switch-case
结构。但其更加强大和灵活。它可以匹配任何类型,并且可以使用模式匹配。
fn main() {
let x = 5;
match x {
1 => println!("One"),
2 | 3 => println!("Two or Three"),
_ => println!("Other"), // `_` 是默认情况
}
}
同样的 match
也可以作为表达式返回值。
fn main() {
let boolean = true;
let binary = match boolean {
false => 0,
true => 1,
};
println!("{} -> {}", boolean, binary);
}
解构
match
可以解构枚举、元组、指针、结构体等数据类型。
- 解构枚举
#[allow(dead_code)]
enum Direction {
North,
South,
East,
West,
}
fn main() {
let direction = Direction::North;
match direction {
Direction::North => println!("Going North"),
Direction::South => println!("Going South"),
Direction::East => println!("Going East"),
Direction::West => println!("Going West"),
}
}
- 解构元组
fn main() {
let triple = (0, -2, 3);
println!("Tell me about {:?}", triple);
match triple {
// 解构出第二个和第三个元素
(0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
(1, ..) => println!("First is `1` and the rest doesn't matter"),
// `..` 可用来忽略元组的其余部分
_ => println!("It doesn't matter what they are"),
// `_` 表示不将值绑定到变量
}
}
- 解构结构体
struct Person {
name: String,
age: u32,
}
fn main() {
let person = Person { name: "Alice".to_string(), age: 30 };
match person {
Person { name: ref n, age: a } => {
println!("Name: {}, Age: {}", n, a);
},
}
}
- 解构指针和引用
对指针来说,解构(
destructure
)和解引用(dereference
)要区分开。
- 解引用使用
*
- 解构使用
&
、ref
、和ref mut
fn main() {
let mut value: i32 = 40;
let value_ref: &mut i32 = &mut value;
match value_ref {
n => {
*n += 1; // 修改值
println!("Updated value: {}", n);
},
}
}
卫语句
在 rust
中,match
语句允许使用匹配守卫(guard clauses),这是一种附加条件,可以在匹配分支中加入额外的逻辑检查。这使得 match
更加灵活,可以处理更复杂的条件。匹配守卫是在 =>
之前使用 if
来指定的一个布尔表达式。只有当该布尔表达式的值为 true
时,才会执行对应的分支。
#[allow(dead_code)]
#[derive(Debug)]
enum Color {
Red(u8, u8, u8), // RGB values
Green(u8, u8, u8),
Blue(u8, u8, u8),
}
fn main() {
let color = Color::Red(255, 0, 0);
match color {
Color::Red(r, g, b) if r == 255 && g == 0 && b == 0 => {
println!("This is pure red.");
},
Color::Green(r, g, _) if r < 100 && g > 150 => {
println!("This green has high green component.");
},
Color::Blue(_, _, _) => {
println!("This is some shade of blue.");
},
_ => {
println!("Unknown color.");
},
}
}
绑定
在 rust
中,match
表达式可以使用 @
符号来绑定一个匹配到的值到一个变量。这种方式允许你在匹配的同时获取这个值,以便在匹配体中使用。
fn main() {
let value = 42;
match value {
n @ 1..=10 => println!("The value is between 1 and 10: {}", n),
n @ 11..=20 => println!("The value is between 11 and 20: {}", n),
n @ 21..=30 => println!("The value is between 21 and 30: {}", n),
n @ 31..=40 => println!("The value is between 31 and 40: {}", n),
n @ 41..=50 => println!("The value is between 41 and 50: {}", n),
_ => println!("The value is out of range"),
}
}
可以使用绑定来“解构” enum
变体,例如 Option
。
fn some_number() -> Option<u32> {
Some(42)
}
fn main() {
match some_number() {
// 得到 `Some` 可变类型,如果它的值(绑定到 `n` 上)等于 42,则匹配。
Some(n @ 42) => println!("The Answer: {}!", n),
// 匹配任意其他数字。
Some(n) => println!("Not interesting... {}", n),
// 匹配任意其他值(`None` 可变类型)。
_ => (),
}
}
循环语句
while
while
循环会在给定的条件为真时反复执行一段代码。
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("Liftoff!");
}
for
for
循环遍历集合或其他可迭代对象中的每一个元素,如数组、范围、集合等。
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
// 使用 range 创建一个从 1 到 9 的序列
for i in 1..10 {
println!("num is: {}", i);
}
}
loop
loop
循环是一个无限循环,除非显式地退出它。通常使用 break
或 return
语句来退出循环。
fn main() {
let mut count = 0;
loop {
count += 1;
if count == 5 {
break; // 当计数达到 5 时退出循环
}
println!("Counting up: {}", count);
}
println!("Loop finished!");
}
嵌套循环和标签
在 rust
中,你可以使用 'label
标签(labels)来创建嵌套循环或控制嵌套循环的行为。标签是一个标识符,后面跟着一个冒号,可以用于标识一个循环。然后,你可以使用 break
或 continue
语句配合标签来跳出指定的循环。
fn main() {
'outer: loop {
println!("Starting outer loop iteration.");
'inner: loop {
println!("Starting inner loop iteration.");
let should_break_outer = true;
if should_break_outer {
break 'outer; // 跳出外层循环
}
let should_continue_inner = false;
if should_continue_inner {
continue 'inner; // 继续内层循环的下一次迭代
}
println!("Inner loop completed this iteration.");
}
}
println!("Both loops have been exited.");
}
从 loop
循环返回值
在 rust
中,loop
循环本身没有直接返回值的功能,但它可以通过 break
语句配合表达式来从 loop
中返回一个值。具体来说,break
语句后面跟上一个表达式,这个表达式的结果将会作为 loop
循环的返回值。
fn main() {
let result = loop {
let x = 5;
let y = 10;
// 条件满足时,返回一个值
if x + y > 10 {
break x + y; // 使用 break 返回值
}
};
println!("The result is: {}", result);
}
if let
和 while let
在 rust
中,if let
和 while let
是两个非常有用的模式匹配工具,用来处理枚举类型中的某些变体,主要用于简化对 Option
和 Result
枚举类型的处理。这两个结构允许你更简洁地编写代码,同时保持良好的可读性和安全性。
if let
if let
用于在条件语句中进行模式匹配。它允许你匹配某个表达式的特定模式,并在匹配成功时执行相应的代码。
fn main() {
let some_value = Some(42);
if let Some(x) = some_value {
println!("Got a value: {}", x);
} else {
println!("No value!");
}
}
while let
while let
主要用于循环场景,类似于 while
循环,但同样适用于模式匹配。它可以在匹配成功时持续执行循环体内的代码,直到不再匹配为止。
fn main() {
let numbers = vec![Some(1), Some(2), Some(3), None, Some(4)];
let mut iterator = numbers.into_iter();
while let Some(Some(x)) = iterator.next() {
println!("Got a number: {}", x);
}
}
跳出控制
在 rust
中,break
、continue
和 return
是三种常用的流程控制关键字,它们各自有不同的用途和效果。
break
break
语句用于立即退出一个循环(如 loop
、for
、while
),并可选择性地返回一个值。
fn main() {
for i in 0..10 {
if i == 5 {
break; // 当 i 等于 5 时,跳出循环
}
println!("{}", i);
}
println!("Loop ended");
}
continue
continue
语句用于跳过当前循环的剩余代码,并直接开始下一次循环迭代。
fn main() {
for i in 0..10 {
if i % 2 == 0 {
continue; // 如果 i 是偶数,则跳过本次循环
}
println!("{}", i); // 只会打印奇数
}
}
return
return
关键字用于从函数中返回一个值并立即退出该函数。如果没有指定返回值,则默认返回 ()
(即单元类型)。
fn add(a: i32, b: i32) -> i32 {
return a + b; // 返回 a 和 b 的和
}
fn main() {
let sum = add(5, 7);
println!("The sum is {}", sum);
}
总结
- 条件语句:
if
和match
用于根据不同的条件执行不同的代码块。 - 循环语句:
loop
,while
, 和for
分别用于无限循环、条件循环和遍历循环。 - 模式匹配语句:
if let
和while let
用于简洁地处理Option
和Result
类型。 - 跳出语句:
break
、continue
和return
作为流程控制关键字,可以提前跳出流程。
rust
提供了灵活且强大的流程控制方式,包括条件语句、循环语句、模式匹配等。这些控制结构使得 rust
适用于多种编程场景,并能够编写高效和安全的代码。