Skip to content

Rust - 函数

函数是 Rust 程序的基本构建块。它们封装了特定的任务,使代码可重用、可读且易于维护。函数将程序组织成逻辑上自包含的单元。

在 Rust 中,你使用 fn 关键字定义函数,后跟函数名、用于参数的圆括号 () 和用于函数体的花括号 {}。函数名通常使用 snake_case 命名约定。

// `main` 函数是每个 Rust 可执行文件的入口点。
fn main() {
println!("Hello from main function!");
// 调用另一个函数
another_function();
}
// 定义另一个函数
fn another_function() {
println!("Hello from another function!");
}
Hello from main function!
Hello from another function!

函数可以接受称为**参数(parameters)**的输入。在函数签名中,你必须声明每个参数的名称和类型。这允许你将值传递给函数进行处理。

fn main() {
print_value(10);
print_sum(5, 6);
}
// 一个带有一个 i32 类型参数的函数
fn print_value(x: i32) {
println!("The value is: {}", x);
}
// 一个带有两个参数的函数
fn print_sum(x: i32, y: i32) {
println!("The sum is: {}", x + y);
}

Rust 函数体由一系列语句组成,最后可以是一个可选的表达式。**语句(Statements)**是执行操作但不返回值(例如 let y = 6;)的指令。**表达式(Expressions)**会求值并产生一个结果值(例如 5 + 6)。

函数可以将值返回给调用它的代码。返回类型在箭头 -> 后面声明。返回的值是函数体中最后一个表达式的值。你也可以使用 return 关键字来提前从函数返回。

fn main() {
let sum = add_five(10);
println!("10 + 5 = {}", sum);
let product = multiply(8, 7);
println!("8 * 7 = {}", product);
}
// 此函数返回一个 i32。
// `x + 5` 这一行是一个表达式,因为它在最后一行,
// 其值会自动返回。
fn add_five(x: i32) -> i32 {
x + 5 // 这里没有分号!
}
// 这个函数也返回一个 i32,但使用了 `return` 关键字。
fn multiply(x: i32, y: i32) -> i32 {
return x * y; // 这里的 `;` 是可选的,但建议保留。
}
10 + 5 = 15
8 * 7 = 56

你向函数传递参数的方式直接与 Rust 的所有权系统交互。与其思考“按值传递(pass-by-value)”和“按引用传递(pass-by-reference)”,不如更准确地将其理解为移动所有权或借用。

当你将变量传递给函数时,数据的所有权会**移动(moved)**到函数的参数中。原始变量将不能再使用。这适用于未实现 Copy trait 的类型,例如 String 或 Vec<T>。

fn main() {
let s = String::from("hello");
takes_ownership(s);
// 下面这行代码将无法编译,因为 `s` 的值已被移动。
// println!("{}", s);
}
fn takes_ownership(some_string: String) {
println!("I now own the string: {}", some_string);
} // `some_string` 在此处被丢弃,其内存被释放。

要在不获取所有权的情况下使用值,你可以传递一个引用(reference)。这被称为借用(borrowing)。调用者保留所有权。引用默认是不可变的。

fn main() {
let s1 = String::from("hello");
// 传递字符串的不可变引用。
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
// `s1` 仍然有效,可以在这里使用。
}
// 此函数借用 String 而不是获取所有权。
fn calculate_length(s: &String) -> usize {
s.len()
} // `s` 超出作用域,但它引用的数据不会被丢弃。

如果你需要修改借用的值,你可以使用 &mut 传递一个可变引用(mutable reference)。在特定作用域内,你只能拥有一个对特定数据的可变引用。

fn main() {
let mut s = String::from("hello");
println!("Original string: {}", s);
// 传递一个可变引用。
change(&mut s);
println!("Modified string: {}", s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
Original string: hello
Modified string: hello, world