函数是 Rust 程序的基本构建块。Rust 中的函数通过 fn 关键字定义,具有强类型、所有权系统和丰富的特性。
1. 函数定义
基本语法
rust
// 函数定义
fn greet() {
println!("Hello, world!");
}
// 带参数的函数
fn greet_person(name: &str) {
println!("Hello, {}!", name);
}
// 带返回值的函数
fn add(x: i32, y: i32) -> i32 {
x + y // 注意:没有分号,这是表达式
}
fn main() {
greet();
greet_person("Alice");
let sum = add(5, 3);
println!("5 + 3 = {}", sum);
}
2. 参数和返回值
参数类型
rust
// 基本类型参数
fn print_number(num: i32) {
println!("数字: {}", num);
}
// 引用参数(不获取所有权)
fn print_string(s: &str) {
println!("字符串: {}", s);
}
// 可变引用参数
fn modify_number(num: &mut i32) {
*num += 10;
}
// 所有权转移参数
fn take_ownership(s: String) {
println!("获得所有权: {}", s);
// s 在这里被丢弃
}
fn main() {
let n = 5;
print_number(n); // n 被复制(Copy trait)
let s = String::from("hello");
print_string(&s); // 传递引用,不转移所有权
println!("原字符串: {}", s); // 仍然可用
let mut m = 20;
modify_number(&mut m);
println!("修改后: {}", m); // 30
let owned = String::from("world");
take_ownership(owned);
// println!("{}", owned); // 错误:owned 的所有权已转移
}
返回值
rust
// 显式返回
fn explicit_return(x: i32) -> i32 {
return x * 2; // 显式使用 return
}
// 隐式返回(表达式)
fn implicit_return(x: i32) -> i32 {
x * 2 // 没有分号,这是表达式
}
// 多个返回点
fn find_even(numbers: &[i32]) -> Option<i32> {
for &num in numbers {
if num % 2 == 0 {
return Some(num); // 提前返回
}
}
None // 最后表达式作为返回值
}
// 返回元组(多返回值)
fn calculate(x: i32, y: i32) -> (i32, i32, i32) {
let sum = x + y;
let product = x * y;
let difference = x - y;
(sum, product, difference) // 返回元组
}
// 返回引用
fn get_first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
fn main() {
println!("显式: {}", explicit_return(5)); // 10
println!("隐式: {}", implicit_return(5)); // 10
let nums = [1, 3, 5, 4, 7];
match find_even(&nums) {
Some(n) => println!("找到偶数: {}", n),
None => println!("没找到偶数"),
}
let (s, p, d) = calculate(10, 5);
println!("和: {}, 积: {}, 差: {}", s, p, d);
let text = "Hello World";
let first = get_first_word(text);
println!("第一个单词: {}", first);
}
3. 函数类型和函数指针
函数指针
rust
// 函数定义
fn add(x: i32, y: i32) -> i32 {
x + y
}
fn multiply(x: i32, y: i32) -> i32 {
x * y
}
// 函数指针类型
type MathOp = fn(i32, i32) -> i32;
fn calculate(op: MathOp, x: i32, y: i32) -> i32 {
op(x, y)
}
fn main() {
let op1: fn(i32, i32) -> i32 = add;
let op2 = multiply; // 类型推断
println!("add(3, 4) = {}", op1(3, 4)); // 7
println!("multiply(3, 4) = {}", op2(3, 4)); // 12
// 使用函数指针
println!("计算 add: {}", calculate(add, 5, 6)); // 11
println!("计算 multiply: {}", calculate(multiply, 5, 6)); // 30
// 函数指针数组
let ops: [MathOp; 2] = [add, multiply];
for (i, &op) in ops.iter().enumerate() {
println!("操作 {}: {}", i, op(2, 3));
}
}
4. 高阶函数和闭包
闭包基础
rust
fn main() {
// 基本闭包
let add_one = |x: i32| -> i32 { x + 1 };
println!("add_one(5) = {}", add_one(5)); // 6
// 类型推断
let add_two = |x| x + 2; // 编译器推断类型
println!("add_two(5) = {}", add_two(5)); // 7
// 捕获环境变量
let base = 10;
let add_base = |x| x + base; // 捕获 base
println!("add_base(5) = {}", add_base(5)); // 15
// 可变捕获
let mut counter = 0;
let mut increment = || {
counter += 1;
println!("计数器: {}", counter);
};
increment(); // 1
increment(); // 2
}
闭包作为参数
rust
// 使用泛型和 Fn trait
fn apply_twice<F>(f: F, x: i32) -> i32
where
F: Fn(i32) -> i32,
{
f(f(x))
}
// 直接使用 impl Trait 语法
fn process_numbers(numbers: &[i32], processor: impl Fn(i32) -> i32) -> Vec<i32> {
numbers.iter().map(|&n| processor(n)).collect()
}
// 返回闭包
fn make_multiplier(factor: i32) -> impl Fn(i32) -> i32 {
move |x| x * factor // move 强制获取 factor 的所有权
}
fn main() {
// 传递闭包
let square = |x| x * x;
let result = apply_twice(square, 3);
println!("(3²)² = {}", result); // 81
// 处理数组
let numbers = vec![1, 2, 3, 4, 5];
let doubled = process_numbers(&numbers, |x| x * 2);
println!("翻倍: {:?}", doubled); // [2, 4, 6, 8, 10]
// 获取闭包
let times_three = make_multiplier(3);
println!("5 * 3 = {}", times_three(5)); // 15
}
闭包 trait
rust
fn main() {
// FnOnce - 只能调用一次(获取所有权)
let expensive = || {
println!("消耗资源");
String::from("结果")
};
// FnMut - 可变引用,可调用多次
let mut count = 0;
let mut incrementer = || {
count += 1;
count
};
// Fn - 不可变引用,可调用多次
let printer = |x: i32| println!("值: {}", x);
// 使用不同的闭包 trait
fn call_once<F>(f: F)
where
F: FnOnce() -> String,
{
let result = f();
println!("结果: {}", result);
}
fn call_mut<F>(mut f: F)
where
F: FnMut() -> i32,
{
for _ in 0..3 {
println!("调用: {}", f());
}
}
fn call<F>(f: F, value: i32)
where
F: Fn(i32),
{
f(value);
}
call_once(expensive);
call_mut(incrementer);
call(printer, 42);
}
5. 方法(关联函数)
结构体方法
rust
struct Rectangle {
width: u32,
height: u32,
}
// impl 块定义方法
impl Rectangle {
// 关联函数(类似静态方法)
fn new(width: u32, height: u32) -> Self {
Rectangle { width, height }
}
// 方法 - &self 参数
fn area(&self) -> u32 {
self.width * self.height
}
// 可变方法 - &mut self 参数
fn scale(&mut self, factor: u32) {
self.width *= factor;
self.height *= factor;
}
// 消费方法 - self 参数
fn into_tuple(self) -> (u32, u32) {
(self.width, self.height)
}
// 方法链
fn with_width(mut self, width: u32) -> Self {
self.width = width;
self
}
fn with_height(mut self, height: u32) -> Self {
self.height = height;
self
}
}
fn main() {
// 使用关联函数创建实例
let mut rect = Rectangle::new(10, 20);
// 调用方法
println!("面积: {}", rect.area()); // 200
// 调用可变方法
rect.scale(2);
println!("缩放后面积: {}", rect.area()); // 800
// 消费方法
let (w, h) = rect.into_tuple();
println!("宽度: {}, 高度: {}", w, h); // 20, 40
// 方法链
let rect2 = Rectangle::new(5, 5)
.with_width(10)
.with_height(15);
println!("新矩形面积: {}", rect2.area()); // 150
}
枚举方法
rust
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn process(&self) {
match self {
Message::Quit => println!("退出程序"),
Message::Move { x, y } => println!("移动到 ({}, {})", x, y),
Message::Write(text) => println!("消息: {}", text),
Message::ChangeColor(r, g, b) => {
println!("颜色改为 RGB({}, {}, {})", r, g, b);
}
}
}
fn is_quit(&self) -> bool {
matches!(self, Message::Quit)
}
}
fn main() {
let messages = [
Message::Quit,
Message::Move { x: 10, y: 20 },
Message::Write("Hello".to_string()),
Message::ChangeColor(255, 0, 0),
];
for msg in &messages {
msg.process();
if msg.is_quit() {
println!("这是一个退出消息");
}
}
}
6. 泛型函数
基础泛型
rust
// 简单的泛型函数
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
// 多个泛型参数
fn pair<T, U>(first: T, second: U) -> (T, U) {
(first, second)
}
// 泛型方法和返回值
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn get_value(&self) -> &T {
&self.value
}
fn transform<U, F>(self, f: F) -> Container<U>
where
F: FnOnce(T) -> U,
{
Container { value: f(self.value) }
}
}
fn main() {
// 使用泛型函数
let numbers = vec![34, 50, 25, 100, 65];
println!("最大数: {}", largest(&numbers)); // 100
let chars = vec!['y', 'm', 'a', 'q'];
println!("最大字符: {}", largest(&chars)); // y
// 使用多个泛型
let p = pair(42, "hello");
println!("配对: {:?}", p); // (42, "hello")
// 使用泛型结构体
let container = Container::new(10);
println!("值: {}", container.get_value());
let transformed = container.transform(|x| x.to_string());
println!("转换后: {}", transformed.get_value()); // "10"
}
泛型约束(trait bounds)
rust
use std::fmt::Display;
// 使用 trait bounds
fn print_item<T: Display>(item: T) {
println!("项目: {}", item);
}
// where 子句(更清晰的语法)
fn compare_and_print<T, U>(a: T, b: U)
where
T: Display + PartialOrd,
U: Display + PartialOrd,
{
println!("a = {}, b = {}", a, b);
if a > b {
println!("a 更大");
} else if a < b {
println!("b 更大");
} else {
println!("相等");
}
}
// 返回实现 trait 的类型
fn make_displayable<T: Display>(value: T) -> impl Display {
value
}
fn main() {
print_item(42); // 数字
print_item("hello"); // 字符串
print_item(3.14); // 浮点数
compare_and_print(10, 20);
compare_and_print("apple", "banana");
let d = make_displayable(100);
println!("可显示的值: {}", d);
}
7. 函数式编程特性
迭代器和适配器
rust
fn process_numbers(numbers: &[i32]) -> Vec<i32> {
numbers.iter()
.filter(|&x| x % 2 == 0) // 只保留偶数
.map(|&x| x * 3) // 乘以3
.filter(|&x| x > 10) // 大于10
.collect() // 收集结果
}
// 自定义迭代器适配器
trait MyIteratorExt: Iterator {
fn skip_odd(self) -> SkipOdd<Self>
where
Self: Sized,
{
SkipOdd { iter: self }
}
}
impl<I: Iterator> MyIteratorExt for I {}
struct SkipOdd<I> {
iter: I,
}
impl<I> Iterator for SkipOdd<I>
where
I: Iterator,
I::Item: std::ops::Rem<Output = I::Item> + From<u8> + PartialEq,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
while let Some(item) = self.iter.next() {
if item % 2.into() != 0.into() {
return Some(item);
}
}
None
}
}
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let result = process_numbers(&numbers);
println!("处理结果: {:?}", result); // [12, 18, 24, 30]
// 使用自定义适配器
let odd_numbers: Vec<_> = numbers.into_iter().skip_odd().collect();
println!("奇数: {:?}", odd_numbers); // [1, 3, 5, 7, 9]
}
8. 高级函数特性
函数重载(通过泛型)
rust
// Rust 没有传统函数重载,但可以通过泛型模拟
trait Greet {
fn greet(&self) -> String;
}
impl Greet for &str {
fn greet(&self) -> String {
format!("Hello, {}!", self)
}
}
impl Greet for i32 {
fn greet(&self) -> String {
format!("Hello, number {}!", self)
}
}
// 泛型函数根据 trait 表现不同行为
fn say_hello<T: Greet>(target: T) {
println!("{}", target.greet());
}
fn main() {
say_hello("Alice"); // Hello, Alice!
say_hello(42); // Hello, number 42!
}
可变参数函数(使用宏或切片)
rust
// 使用切片模拟可变参数
fn sum_all(numbers: &[i32]) -> i32 {
numbers.iter().sum()
}
// 使用宏实现真正可变参数
macro_rules! varargs_sum {
($($x:expr),*) => {
{
let mut sum = 0;
$(sum += $x;)*
sum
}
};
}
fn main() {
// 使用切片版本
let sum1 = sum_all(&[1, 2, 3, 4, 5]);
println!("切片求和: {}", sum1); // 15
// 使用宏版本
let sum2 = varargs_sum!(1, 2, 3, 4, 5);
println!("宏求和: {}", sum2); // 15
let sum3 = varargs_sum!(10, 20, 30);
println!("宏求和2: {}", sum3); // 60
}
9. 错误处理函数
Result 返回
rust
use std::fs::File;
use std::io::{self, Read};
// 返回 Result 的函数
fn read_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?; // ? 运算符传播错误
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
// 自定义错误类型
#[derive(Debug)]
enum AppError {
IoError(io::Error),
ParseError(String),
ValidationError(String),
}
impl From<io::Error> for AppError {
fn from(err: io::Error) -> Self {
AppError::IoError(err)
}
}
fn process_data(path: &str) -> Result<i32, AppError> {
let content = read_file(path)?; // 自动转换错误类型
let number: i32 = content.trim().parse()
.map_err(|e| AppError::ParseError(e.to_string()))?;
if number < 0 {
return Err(AppError::ValidationError(
"数字不能为负数".to_string()
));
}
Ok(number * 2)
}
fn main() {
match process_data("data.txt") {
Ok(result) => println!("处理结果: {}", result),
Err(AppError::IoError(e)) => println!("IO错误: {}", e),
Err(AppError::ParseError(e)) => println!("解析错误: {}", e),
Err(AppError::ValidationError(e)) => println!("验证错误: {}", e),
}
}
Option 返回
rust
// 返回 Option 的函数
fn find_char(s: &str, target: char) -> Option<usize> {
s.chars().position(|c| c == target)
}
fn find_and_process(s: &str, target: char) -> Option<String> {
let pos = find_char(s, target)?; // ? 传播 None
let result = format!("在位置 {} 找到 '{}'", pos, target);
Some(result)
}
fn safe_division(numerator: i32, denominator: i32) -> Option<i32> {
if denominator == 0 {
None
} else {
Some(numerator / denominator)
}
}
fn main() {
// 链式调用
let result = find_and_process("hello", 'l');
match result {
Some(msg) => println!("成功: {}", msg), // 成功: 在位置 2 找到 'l'
None => println!("未找到字符"),
}
// 组合使用
let division_result = safe_division(10, 2)
.and_then(|x| safe_division(x, 5));
println!("除法结果: {:?}", division_result); // Some(1)
}
10. 函数可见性和模块
公有和私有函数
rust
// 模块示例
mod math {
// 私有函数(只能在模块内访问)
fn internal_add(x: i32, y: i32) -> i32 {
x + y
}
// 公有函数
pub fn add(x: i32, y: i32) -> i32 {
internal_add(x, y)
}
// 嵌套模块
pub mod advanced {
pub fn multiply(x: i32, y: i32) -> i32 {
x * y
}
// 父模块可访问
pub(crate) fn secret_operation() -> i32 {
42
}
}
}
fn main() {
// 使用公有函数
println!("3 + 4 = {}", math::add(3, 4));
println!("3 * 4 = {}", math::advanced::multiply(3, 4));
// 以下代码会编译错误
// math::internal_add(1, 2); // 私有函数
// math::advanced::secret_operation(); // 仅 crate 内可见
}
11. 内联函数
内联属性
rust
// 建议内联的小函数
#[inline]
fn small_function(x: i32) -> i32 {
x * x
}
// 强制内联
#[inline(always)]
fn critical_function(x: i32) -> i32 {
x + 1
}
// 建议不要内联
#[inline(never)]
fn large_function(x: i32) -> i32 {
// 假设这里有大量代码
x * 2
}
fn main() {
let a = small_function(5);
let b = critical_function(5);
let c = large_function(5);
println!("a={}, b={}, c={}", a, b, c);
}
12. 函数最佳实践
可读性
rust
// 好的命名和文档
/// 计算两个数的最大公约数
///
/// # 参数
/// * `a` - 第一个整数
/// * `b` - 第二个整数
///
/// # 返回值
/// 返回 a 和 b 的最大公约数
///
/// # 示例
/// ```
/// let gcd = greatest_common_divisor(12, 18);
/// assert_eq!(gcd, 6);
/// ```
fn greatest_common_divisor(mut a: u32, mut b: u32) -> u32 {
while b != 0 {
let temp = b;
b = a % b;
a = temp;
}
a
}
// 单一职责原则
fn process_user_data(name: &str, age: u8) -> String {
// 验证
let validated_name = validate_name(name);
let validated_age = validate_age(age);
// 处理
format_data(validated_name, validated_age)
}
fn validate_name(name: &str) -> &str {
if name.is_empty() {
panic!("名称不能为空");
}
name
}
fn validate_age(age: u8) -> u8 {
if age > 150 {
panic!("年龄无效");
}
age
}
fn format_data(name: &str, age: u8) -> String {
format!("姓名: {}, 年龄: {}", name, age)
}
性能考虑
rust
// 传递引用避免复制
fn process_large_data(data: &[i32]) -> i32 {
data.iter().sum()
}
// 使用 const fn 编译时计算
const fn square(x: i32) -> i32 {
x * x
}
// 返回引用避免分配
fn get_better<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() { a } else { b }
}
fn main() {
// 编译时计算
const VALUE: i32 = square(5);
println!("平方: {}", VALUE); // 25
let large_data = vec![1; 1000];
let sum = process_large_data(&large_data);
println!("总和: {}", sum); // 1000
let longer = get_better("short", "longer");
println!("更长的: {}", longer); // longer
}
Rust 的函数系统结合了强大的类型系统、所有权模型和函数式编程特性,使得代码既安全又高效。合理使用这些特性可以编写出高质量、可维护的 Rust 代码。