4·基础入门入门

函数与返回值

函数与返回值

学习目标

  1. 掌握函数定义语法
  2. 理解参数和返回值
  3. 理解表达式 vs 语句
  4. 掌握提前返回和 return 关键字

核心概念

函数定义

fn greet(name: &str) {
    println!("Hello, {}!", name);
}

fn add(a: i32, b: i32) -> i32 {
    a + b  // 注意:没有分号 = 这是返回值表达式
}

命名规范:函数名用 snake_case(小写下划线)。

参数

fn describe(name: &str, age: u32, height: f64) {
    println!("{} is {} years old, {:.1}m tall", name, age, height);
}

fn main() {
    describe("Alice", 30, 1.65);
}

返回值

// 方式一:最后一个表达式(不加分号)—— 推荐
fn double(x: i32) -> i32 {
    x * 2
}

// 方式二:显式 return —— 用于提前返回
fn find_first_negative(numbers: &[i32]) -> Option<i32> {
    for &n in numbers {
        if n < 0 {
            return Some(n);  // 提前返回
        }
    }
    None
}

表达式 vs 语句

这是 Rust 的核心概念:

fn main() {
    // 语句(statement):执行操作,不返回值
    let x = 5;            // let 语句

    // 表达式(expression):产生值
    5                       // 字面量表达式
    x + 1                   // 算术表达式
    {                       // 块表达式
        let y = 3;
        y + 1               // 块的最后一个表达式是块的值
    }

    // ❌ 加了分号变成语句,没有返回值
    let y = {
        let x = 3;
        x + 1;              // 加了分号 → 语句 → 返回 ()
    };  // y 的类型是 ()
}

多返回值(元组)

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

fn div_rem(a: i32, b: i32) -> (i32, i32) {
    (a / b, a % b)
}

fn main() {
    let (quotient, remainder) = div_rem(17, 5);
    println!("17 / 5 = {} 余 {}", quotient, remainder);
}

永不返回的函数

fn forever() -> ! {
    loop {
        // 永远不会返回
    }
}

fn exit_with_error(msg: &str) -> ! {
    panic!("{}", msg);  // panic! 返回类型是 !
}

实践练习

练习 1:温度转换函数

fn fahrenheit_to_celsius(f: f64) -> f64 {
    (f - 32.0) * 5.0 / 9.0
}

fn celsius_to_fahrenheit(c: f64) -> f64 {
    c * 9.0 / 5.0 + 32.0
}

fn main() {
    let boiling_f = 212.0;
    let boiling_c = fahrenheit_to_celsius(boiling_f);
    println!("{}°F = {}°C", boiling_f, boiling_c);

    let body_c = 37.0;
    let body_f = celsius_to_fahrenheit(body_c);
    println!("{}°C = {}°F", body_c, body_f);
}

练习 2:判断质数

fn is_prime(n: u32) -> bool {
    if n < 2 {
        return false;
    }
    let mut i = 2;
    while i * i <= n {
        if n % i == 0 {
            return false;
        }
        i += 1;
    }
    true
}

fn main() {
    for n in 1..=20 {
        if is_prime(n) {
            print!("{} ", n);
        }
    }
    println!();  // 输出: 2 3 5 7 11 13 17 19
}

练习 3:递归阶乘

fn factorial(n: u64) -> u64 {
    if n <= 1 {
        1
    } else {
        n * factorial(n - 1)
    }
}

fn main() {
    for i in 0..=10 {
        println!("{}! = {}", i, factorial(i));
    }
}

常见错误

1. 返回值加了分号

// ❌ 返回 ()
fn add(a: i32, b: i32) -> i32 {
    a + b;  // 分号让它变成语句
}

// ✅ 去掉分号
fn add(a: i32, b: i32) -> i32 {
    a + b
}

2. 返回类型不匹配

// ❌ 返回 i32 但函数签名是 f64
fn half(x: i32) -> f64 {
    x / 2    // 整数除法,结果是 i32
}

// ✅
fn half(x: i32) -> f64 {
    x as f64 / 2.0
}

3. 忘记处理返回值

fn get_value() -> i32 { 42 }

fn main() {
    get_value();  // ⚠️ 返回值被忽略(编译器警告)

    let v = get_value();  // ✅
}

小结

要点说明
fn name(args) -> Type { ... }函数定义
不加分号表达式,作为返回值
加分号语句,返回 ()
return提前返回(通常用表达式语法)
(T1, T2)元组,用于多返回值
-> !永不返回(发散函数)

练习编辑器

rust
Loading...