文档
Rust 例程:所有权与借用初体验
目标
通过一个命令行程序展示 Rust 核心概念:所有权、借用、模式匹配、Result 错误处理。
完整代码
use std::fs;
use std::io::{self, Write};
/// 统计文件中的单词数
fn count_words(text: &str) -> usize {
text.split_whitespace().count()
}
/// 统计文件中的行数
fn count_lines(text: &str) -> usize {
text.lines().count()
}
/// 读取文件内容,返回 Result
fn read_file(path: &str) -> Result<String, io::Error> {
fs::read_to_string(path)
}
/// 程序入口
fn main() {
let args: Vec<String> = std::env::args().collect();
// 模式匹配处理参数
let path = match args.get(1) {
Some(p) => p,
None => {
eprintln!("用法: cargo run -- <文件路径>");
std::process::exit(1);
}
};
// Result 错误处理
let content = match read_file(path) {
Ok(c) => c,
Err(e) => {
eprintln!("读取文件失败: {}", e);
std::process::exit(1);
}
};
// 借用:content 的所有权不转移,只是借用给函数
let words = count_words(&content); // & 不可变借用
let lines = count_lines(&content); // 可以同时多个不可变借用
println!("文件: {}", path);
println!("行数: {}", lines);
println!("单词数: {}", words);
// ── 所有权演示 ──
let s1 = String::from("hello");
let s2 = s1; // s1 所有权移动到 s2
// println!("{}", s1); // ❌ 编译错误!s1 已失效
println!("s2 拥有: {}", s2);
let s3 = s2.clone(); // 深拷贝
println!("s2: {}, s3: {} (clone 后两者都有效)", s2, s3);
// ── 借用演示 ──
let mut data = String::from("Rust");
let r1 = &data; // 不可变借用
let r2 = &data; // 可以多个不可变借用
println!("r1: {}, r2: {}", r1, r2);
// r1、r2 最后一次使用后,可以可变借用
let r3 = &mut data; // 可变借用
r3.push_str("acean");
println!("修改后: {}", r3);
}
运行步骤
cargo new rust-demo && cd rust-demo
# 将上面代码写入 src/main.rs
echo "Hello Rust
Welcome to ownership world" > test.txt
cargo run -- test.txt
预期输出
文件: test.txt
行数: 2
单词数: 8
s2 拥有: hello
s2: hello, s3: hello (clone 后两者都有效)
r1: Rust, r2: Rust
修改后: Rustacean
关键要点
| 概念 | 规则 |
|---|---|
| 所有权 | 每个值有且仅有一个所有者 |
| 移动 | 赋值/传参默认移动(非 Copy 类型) |
| 借用 | &T 不可变借用(可多个),&mut T 可变借用(唯一) |
| 生命周期 | 引用不能比它指向的值活得更久 |