【Rust】函数

函数是 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 代码。

相关推荐
huatian52 小时前
Rust 语法整理
开发语言·后端·rust
九月生5 小时前
Rust CLI 项目构建指南
rust
徐安安ye7 小时前
Flutter 与 Rust 混合开发:打造毫秒级响应的高性能计算引擎
开发语言·flutter·rust
浪客川7 小时前
rust入门案例-猜数字游戏
开发语言·rust
Source.Liu17 小时前
【Rust】方法
rust
Source.Liu17 小时前
【Rust】if表达式详解
rust
Source.Liu19 小时前
【Rust】循环控制结构
rust
Source.Liu19 小时前
【Rust】元组:轻量级数据组合利器
rust
RustFS1 天前
RustFS 如何实现对象存储的前端直传?
vue.js·docker·rust