参数与返回值 #

一、参数传递 #

1.1 值传递 #

rust
fn double(mut x: i32) -> i32 {
    x *= 2;
    x
}

fn main() {
    let a = 5;
    let b = double(a);
    println!("a = {}, b = {}", a, b);  // a = 5, b = 10
}

1.2 引用传递 #

rust
fn print_length(s: &String) {
    println!("Length: {}", s.len());
}

fn main() {
    let s = String::from("hello");
    print_length(&s);
    println!("s still valid: {}", s);
}

1.3 可变引用 #

rust
fn push_str(s: &mut String, suffix: &str) {
    s.push_str(suffix);
}

fn main() {
    let mut s = String::from("hello");
    push_str(&mut s, ", world");
    println!("{}", s);
}

二、多返回值 #

2.1 元组返回 #

rust
fn divide(dividend: i32, divisor: i32) -> (i32, i32) {
    (dividend / divisor, dividend % divisor)
}

fn main() {
    let (quotient, remainder) = divide(10, 3);
    println!("商: {}, 余数: {}", quotient, remainder);
}

2.2 解构返回值 #

rust
fn min_max(numbers: &[i32]) -> (i32, i32) {
    let mut min = numbers[0];
    let mut max = numbers[0];
    
    for &num in numbers {
        if num < min { min = num; }
        if num > max { max = num; }
    }
    
    (min, max)
}

fn main() {
    let numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
    let (min, max) = min_max(&numbers);
    println!("最小: {}, 最大: {}", min, max);
}

三、Option 返回 #

3.1 返回 Option #

rust
fn find_first_even(numbers: &[i32]) -> Option<usize> {
    for (i, &num) in numbers.iter().enumerate() {
        if num % 2 == 0 {
            return Some(i);
        }
    }
    None
}

fn main() {
    let numbers = vec![1, 3, 5, 4, 7];
    
    match find_first_even(&numbers) {
        Some(index) => println!("第一个偶数索引: {}", index),
        None => println!("没有偶数"),
    }
}

3.2 使用 ? 运算符 #

rust
fn get_last_char(s: &str) -> Option<char> {
    s.chars().last()
}

fn process(s: &str) -> Option<String> {
    let c = get_last_char(s)?;
    Some(format!("最后一个字符: {}", c))
}

fn main() {
    println!("{:?}", process("hello"));
    println!("{:?}", process(""));
}

四、Result 返回 #

4.1 返回 Result #

rust
fn divide_checked(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("除数不能为零"))
    } else {
        Ok(a / b)
    }
}

fn main() {
    match divide_checked(10, 2) {
        Ok(result) => println!("结果: {}", result),
        Err(e) => println!("错误: {}", e),
    }
    
    match divide_checked(10, 0) {
        Ok(result) => println!("结果: {}", result),
        Err(e) => println!("错误: {}", e),
    }
}

4.2 错误传播 #

rust
use std::fs::File;
use std::io::{self, Read};

fn read_file_content(path: &str) -> io::Result<String> {
    let mut file = File::open(path)?;
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    Ok(content)
}

fn main() {
    match read_file_content("test.txt") {
        Ok(content) => println!("内容: {}", content),
        Err(e) => println!("错误: {}", e),
    }
}

五、默认参数 #

Rust不支持默认参数,但可以使用其他方式:

5.1 使用 Option #

rust
fn greet(name: &str, greeting: Option<&str>) {
    let greeting = greeting.unwrap_or("Hello");
    println!("{}, {}!", greeting, name);
}

fn main() {
    greet("Alice", None);
    greet("Bob", Some("Hi"));
}

5.2 使用结构体 #

rust
struct GreetOptions {
    name: String,
    greeting: String,
    punctuation: String,
}

impl GreetOptions {
    fn new(name: &str) -> Self {
        GreetOptions {
            name: name.to_string(),
            greeting: String::from("Hello"),
            punctuation: String::from("!"),
        }
    }
    
    fn greeting(mut self, greeting: &str) -> Self {
        self.greeting = greeting.to_string();
        self
    }
    
    fn punctuation(mut self, punctuation: &str) -> Self {
        self.punctuation = punctuation.to_string();
        self
    }
    
    fn build(self) -> String {
        format!("{}, {}{}", self.greeting, self.name, self.punctuation)
    }
}

fn main() {
    let msg = GreetOptions::new("Alice")
        .greeting("Hi")
        .punctuation(".")
        .build();
    println!("{}", msg);
}

六、可变参数 #

6.1 使用宏 #

rust
fn main() {
    println!("Sum: {}", sum!(1, 2, 3, 4, 5));
}

macro_rules! sum {
    ($($x:expr),*) => {
        {
            let mut total = 0;
            $(
                total += $x;
            )*
            total
        }
    };
}

6.2 使用切片 #

rust
fn sum(numbers: &[i32]) -> i32 {
    numbers.iter().sum()
}

fn main() {
    let result = sum(&[1, 2, 3, 4, 5]);
    println!("Sum: {}", result);
}

七、函数指针 #

7.1 函数类型 #

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

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

fn calculate(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32 {
    op(a, b)
}

fn main() {
    let result1 = calculate(add, 5, 3);
    let result2 = calculate(multiply, 5, 3);
    
    println!("add: {}", result1);
    println!("multiply: {}", result2);
}

7.2 函数作为返回值 #

rust
fn get_operator(op: &str) -> Option<fn(i32, i32) -> i32> {
    match op {
        "+" => Some(add),
        "*" => Some(multiply),
        _ => None,
    }
}

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

fn main() {
    if let Some(op) = get_operator("+") {
        println!("Result: {}", op(5, 3));
    }
}

八、实践示例 #

8.1 链式处理 #

rust
fn process(s: String) -> String {
    s
}

fn add_prefix(mut s: String) -> String {
    s.insert_str(0, "Prefix: ");
    s
}

fn add_suffix(mut s: String) -> String {
    s.push_str(" [Suffix]");
    s
}

fn main() {
    let result = process(String::from("hello"))
        .pipe(add_prefix)
        .pipe(add_suffix);
    
    println!("{}", result);
}

trait Pipe<T> {
    fn pipe<F>(self, f: F) -> T where F: FnOnce(Self) -> T;
}

impl<T> Pipe<T> for T {
    fn pipe<F>(self, f: F) -> T where F: FnOnce(Self) -> T {
        f(self)
    }
}

8.2 回调函数 #

rust
fn process_with_callback(data: &[i32], callback: fn(i32) -> i32) -> Vec<i32> {
    data.iter().map(|&x| callback(x)).collect()
}

fn double(x: i32) -> i32 { x * 2 }
fn square(x: i32) -> i32 { x * x }

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    
    let doubled = process_with_callback(&numbers, double);
    println!("Doubled: {:?}", doubled);
    
    let squared = process_with_callback(&numbers, square);
    println!("Squared: {:?}", squared);
}

九、总结 #

本章学习了:

  • 参数传递方式
  • 多返回值处理
  • Option 和 Result 返回
  • 默认参数替代方案
  • 可变参数处理
  • 函数指针

下一章,我们将学习闭包与迭代器。

最后更新:2026-03-27