Skip to content

Day 4: 函数与控制流

今天是《30天精通Rust语言》系列的第四天。我们将学习Rust中的函数定义和控制流语句。函数是组织代码的基本单元,控制流则决定了程序的执行顺序。

Rust使用 fn 关键字定义函数。函数可以在文件任意位置定义,顺序不影响(不像C语言需要先声明后调用)。

fn greet() {
println!("Hello, Rust!");
}
fn main() {
greet();
}

函数参数需要标注类型:

fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
greet("Rust");
greet("World");
}

Rust函数默认返回最后一个表达式的值,或使用 return 关键字显式返回:

fn add(a: i32, b: i32) -> i32 {
a + b // 注意:不能加分号,否则变成语句而非表达式
}
fn subtract(a: i32, b: i32) -> i32 {
return a - b; // 显式返回
}
fn main() {
let result = add(5, 3);
println!("5 + 3 = {}", result);
let result = subtract(10, 4);
println!("10 - 4 = {}", result);
}

重要:Rust中大多数语句不返回值,因此 a + b; 末尾的分号会使函数返回 ()(空元组),而非 a + b 的值。

函数可以通过元组返回多个值:

fn min_max(numbers: &[i32]) -> (i32, i32) {
let min = numbers.iter().min().unwrap();
let max = numbers.iter().max().unwrap();
(*min, *max)
}
fn main() {
let nums = [3, 1, 4, 1, 5, 9, 2, 6];
let (min, max) = min_max(&nums);
println!("Min: {}, Max: {}", min, max);
}

Rust的 if 是表达式,可以有返回值:

fn main() {
let number = 7;
if number < 5 {
println!("condition was true");
} else if number < 10 {
println!("condition was false, but number < 10");
} else {
println!("condition was false, and number >= 10");
}
}

当只关心一种模式时,if let 提供了更简洁的写法:

fn main() {
let some_value: Option<i32> = Some(42);
if let Some(value) = some_value {
println!("Got value: {}", value);
}
}

Rust提供了三种循环结构:loop、while 和 for。

loop 是无限循环,需要手动 break 退出:

fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // break可以返回值
}
};
println!("Result: {}", result); // 输出20
}

while 循环在条件为真时重复执行:

fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("LIFTOFF!!!");
}

for 循环是最常用的遍历方式,安全且高效:

fn main() {
// 遍历范围
for i in 1..=5 {
println!("i = {}", i);
}
// 遍历数组
let array = [10, 20, 30];
for element in array.iter() {
println!("Element: {}", element);
}
// 使用.rev()反转范围
for i in (1..=3).rev() {
println!("{}!", i);
}
}

让我们编写一个计算阶乘的程序,综合运用函数和循环:

fn factorial(n: u64) -> u64 {
if n == 0 {
return 1;
}
let mut result = 1;
for i in 1..=n {
result *= i;
}
result
}
fn main() {
let nums = [0, 1, 2, 3, 4, 5, 10];
for n in nums {
println!("{}! = {}", n, factorial(n));
}
}

输出:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
10! = 3628800

Rust的 match 是强大的模式匹配结构,类似于其他语言的switch但更强大:

fn main() {
let number = 7;
match number {
1 => println!("One"),
2 => println!("Two"),
3 => println!("Three"),
4..=10 => println!("Between 4 and 10"),
_ => println!("Something else"),
}
}

match 会穷尽所有可能,因此处理 _ 分支是必要的(类似于default)。

今天的实践任务:

  1. 编写一个函数 is_even(n: i32) -> bool,判断一个数是否为偶数。
  2. 编写一个函数 fibonacci(n: u32) -> u32,返回斐波那契数列第n项。
  3. 编写一个程序,使用循环计算1到100之间所有奇数的和。
  4. 改写上述斐波那契函数,使用递归实现,对比两种实现的差异。
  5. 使用 match 编写一个简单的石头剪刀布游戏判断逻辑。

问:为什么Rust函数返回值不能加尾部分号?

答:在Rust中,分号结束一个语句,语句返回值是 ()。若要返回表达式的值,该表达式必须是函数的最后一行且不加分的表达式。

问:三种循环应该如何选择?

答:for 循环是最推荐的,适合遍历范围或集合。while 适合在条件为真时重复执行的场景。loop 适合需要手动控制循环退出的场景。

今天我们学习了Rust中的函数定义和控制流语句:

  • 函数使用 fn 定义,支持参数和返回值。
  • if 是表达式,可以有返回值。
  • 三种循环:loop(无限循环)、while(条件循环)、for(遍历循环)。
  • match 提供强大的模式匹配功能。

明天我们将学习Rust最核心的概念:所有权系统。准备好迎接挑战!