函数(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!("闭包测试通过!");
}
最佳实践
- 函数名使用蛇形命名法:
calculate_area
而不是calculateArea
- 保持函数简短:一个函数应该只做一件事
- 使用有意义的参数名:参数名应该清楚地表达其用途
- 优先使用表达式:在函数末尾返回值时,省略
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!("不能除以零!"),
}
}