跳到主要内容

函数(Functions)

函数(Functions)是 Rust 代码中的主要构建块。你已经见过语言中最重要的函数之一:main 函数,它是很多程序的入口点。

函数定义

Rust 中的函数定义以 fn 开始,后跟函数名和一对圆括号:

fn main() {
println!("Hello, world!");

another_function();
}

fn another_function() {
println!("Another function.");
}

函数参数

函数可以定义参数(parameters),参数是特殊变量,是函数签名的一部分:

fn main() {
print_labeled_measurement(5, 'h');
}

fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {value}{unit_label}");
}

多个参数

fn main() {
let result = add(5, 3);
println!("5 + 3 = {}", result);
}

fn add(x: i32, y: i32) -> i32 {
x + y // 注意:没有分号,这是一个表达式
}

函数返回值

函数可以向调用它的代码返回值。我们不对返回值命名,但要在箭头(->)后声明它的类型:

fn five() -> i32 {
5
}

fn main() {
let x = five();
println!("The value of x is: {x}");
}

提前返回

使用 return 关键字可以提前从函数返回:

fn main() {
let result = check_number(10);
println!("Result: {}", result);
}

fn check_number(x: i32) -> &'static str {
if x > 0 {
return "positive"; // 提前返回
}

if x < 0 {
"negative" // 最后的表达式,不需要 return
} else {
"zero"
}
}

语句和表达式

Rust 是一门基于表达式的语言,这是一个需要理解的重要区别:

  • 语句(Statements)是执行一些操作但不返回值的指令
  • 表达式(Expressions)计算并产生一个值
fn main() {
let y = {
let x = 3;
x + 1 // 这是一个表达式,注意没有分号
};

println!("The value of y is: {y}"); // 输出:4
}

表达式示例

fn main() {
// 数学运算是表达式
let sum = 5 + 10;

// 函数调用是表达式
let result = multiply(3, 4);

// 代码块是表达式
let value = {
let inner = 10;
inner * 2 // 返回 20
};

println!("sum: {}, result: {}, value: {}", sum, result, value);
}

fn multiply(a: i32, b: i32) -> i32 {
a * b // 表达式,返回计算结果
}

函数作为值

在 Rust 中,函数也是值,可以赋给变量:

fn main() {
let operation = add; // 将函数赋给变量
let result = operation(5, 3);
println!("Result: {}", result);
}

fn add(a: i32, b: i32) -> i32 {
a + b
}

高阶函数

函数可以接受其他函数作为参数:

fn main() {
let numbers = vec![1, 2, 3, 4, 5];

let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
println!("Doubled: {:?}", doubled);

let sum = calculate(10, 5, add);
let product = calculate(10, 5, multiply);

println!("Sum: {}, Product: {}", sum, product);
}

fn add(a: i32, b: i32) -> i32 {
a + b
}

fn multiply(a: i32, b: i32) -> i32 {
a * b
}

fn calculate(x: i32, y: i32, operation: fn(i32, i32) -> i32) -> i32 {
operation(x, y)
}

闭包简介

闭包是可以捕获其环境的匿名函数:

fn main() {
let x = 4;

// 闭包捕获了变量 x
let equal_to_x = |z| z == x;

let y = 4;
assert!(equal_to_x(y));

println!("闭包测试通过!");
}

最佳实践

  1. 函数名使用蛇形命名法calculate_area 而不是 calculateArea
  2. 保持函数简短:一个函数应该只做一件事
  3. 使用有意义的参数名:参数名应该清楚地表达其用途
  4. 优先使用表达式:在函数末尾返回值时,省略 return 和分号
// 好的函数设计
fn calculate_circle_area(radius: f64) -> f64 {
std::f64::consts::PI * radius * radius
}

// 清晰的错误处理
fn divide(dividend: f64, divisor: f64) -> Option<f64> {
if divisor == 0.0 {
None
} else {
Some(dividend / divisor)
}
}

fn main() {
let area = calculate_circle_area(5.0);
println!("圆的面积: {:.2}", area);

match divide(10.0, 2.0) {
Some(result) => println!("10 / 2 = {}", result),
None => println!("不能除以零!"),
}
}