实战总结
> 综合运用本章函数知识,通过实战示例巩固函数定义、参数传递和闭包使用。
调试技巧
使用 dbg! 调试函数
rust
▶ Runfn calculate(x: i32, y: i32) -> i32 {
let sum = dbg!(x + y);
let product = dbg!(x * y);
let result = sum + product;
dbg!(result)
}
fn main() {
let r = calculate(3, 5);
println!("最终结果:{}", r);
}输出:
[src/main.rs:3] x + y = 8
[src/main.rs:4] x * y = 15
[src/main.rs:5] result = 23
最终结果:23打印函数签名
rust
▶ Runfn my_function(x: i32, y: String) -> (i32, String) {
(x, y)
}
fn main() {
// 打印类型信息
println!("函数类型:{:?}", std::any::type_name_of_val(&my_function));
}常见错误
错误 1:忘记返回类型
rust
▶ Run// ❌ 错误:有返回值但没声明返回类型
// fn add(x: i32, y: i32) {
// x + y
// }
// ✅ 正确
fn add(x: i32, y: i32) -> i32 {
x + y
}错误信息:
error[E0308]: mismatched types
--> src/main.rs:3:1
|
2 | fn add(x: i32, y: i32) { // 隐含返回 ()
| - help: add `-> i32` to return the type
3 | x + y
| ^^^^^ expected `()`, found `i32`错误 2:语句和表达式混淆
rust
▶ Run// ❌ 错误:分号让表达式变成语句
// fn add(x: i32, y: i32) -> i32 {
// let result = x + y; // 分号,语句
// } // 返回 () 而不是 i32
// ✅ 正确
fn add(x: i32, y: i32) -> i32 {
let result = x + y; // 语句
result // 表达式,返回值
}错误信息:
error[E0308]: mismatched types
--> src/main.rs:4:1
|
2 | fn add(x: i32, y: i32) -> i32 {
| --- expected `i32` because of return type
3 | let result = x + y;
4 | }
| ^^^^^ expected `i32`, found `()`错误 3:所有权问题
rust
▶ Runfn take_string(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("hello");
take_string(s);
// println!("{}", s); // ❌ 错误:s 已被移动
}错误信息:
error[E0382]: borrow of moved value: `s`
--> src/main.rs:6:20
|
5 | let s = String::from("hello");
| - move occurs because `s` has type `String`
6 | take_string(s);
| - value moved here
7 | println!("{}", s); // ❌ 错误
| ^ value borrowed here after move修复:
rust
▶ Run// 方法 1:传递引用
fn take_string(s: &String) {
println!("{}", s);
}
// 方法 2:传递&str(更佳)
fn take_string(s: &str) {
println!("{}", s);
}
// 方法 3:返回所有权
fn take_string(s: String) -> String {
println!("{}", s);
s
}错误 4:参数类型不匹配
rust
▶ Runfn print_name(name: &str) {
println!("{}", name);
}
fn main() {
let name = String::from("Alice");
// print_name(name); // ❌ 类型不匹配
print_name(&name); // ✅ 传递引用
}练习
练习 1:数学函数
实现以下函数:
is_prime(n: u32) -> bool- 判断是否为质数gcd(a: u32, b: u32) -> u32- 计算最大公约数fibonacci(n: u32) -> u32- 计算斐波那契数列第 n 项
练习 2:字符串处理
实现以下函数:
reverse_string(s: &str) -> String- 反转字符串is_palindrome(s: &str) -> bool- 判断是否为回文count_vowels(s: &str) -> usize- 统计元音字母数量
练习 3:数据结构
实现一个函数,接受一个整数数组,返回一个包含以下统计信息的结构体:
- 最小值
- 最大值
- 平均值
- 中位数
小结
函数语法要点
| 概念 | 语法 | 说明 |
|---|---|---|
| 函数定义 | fn name(params) -> Type { body } | 基本结构 |
| 参数类型 | x: i32 | 必须显式标注 |
| 返回类型 | -> i32 | 有返回值时必须 |
| 表达式返回 | x + y | 无分号 |
| 语句返回 | return x + y | 显式返回或提前返回 |
| 单元类型 | () | 无返回值时的隐含返回 |
关键概念
表达式 vs 语句
- 表达式返回值(无分号)
- 语句执行操作(有分号)
所有权传递
- 传递值:转移所有权
- 传递引用:借用
参数命名
- 使用蛇形命名(snake_case)
- 选择有意义的名字
最佳实践
- 函数应该短小,只做一件事
- 函数名应该清楚表达其功能
- 优先使用
&str而不是&String - 使用
Option或Result处理可能的失败 - 写文档注释说明函数的用途
练习题
详见:练习题