一、Rust基础概述
1.1 语法设计目标
- 安全、并发、性能并重,静态强类型与零成本抽象。
- 表达式为核心,尽量在编译期发现问题。
- 生态与工具链:
rustup管理工具链,cargo构建与依赖管理,rust-analyzer提升 IDE 体验。
1.2 程序基本结构
arduino
fn main() {
println!("Hello, Rust");
}
二、变量、所有权与借用
2.1 变量、常量与遮蔽
讲解:变量默认不可变,使用 mut 声明可变变量;遮蔽允许用同名新绑定覆盖旧值但保持不可变语义;const 为编译期常量,需显式类型。
示例:完整可执行的变量、遮蔽与常量演示
ini
fn main() {
let x = 1;
let x = x + 1;
let mut y = 0;
y += 1;
const MAX: u32 = 100_000;
println!("x={}", x);
println!("y={}", y);
println!("MAX={}", MAX);
}
2.2 所有权、移动、复制与克隆
讲解:String 等堆分配类型在赋值时会发生所有权移动;clone 执行深拷贝保留两个独立所有权;诸如整数等实现 Copy 的标量类型按值复制,无需移动。
示例:完整可执行的所有权与克隆演示
rust
fn main() {
let s = String::from("hi");
let t = s;
println!("moved: {}", t);
let u = t.clone();
println!("cloned: t={}, u={}", t, u);
let a = 1;
let b = a;
println!("copy: a={}, b={}", a, b);
}
2.3 借用与可变借用
讲解:不可变借用允许只读访问;可变借用在同一时刻只能存在一个以保证数据一致性;借用不转移所有权。
示例:完整可执行的借用演示
rust
fn len(s: &String) -> usize { s.len() }
fn push_exclaim(s: &mut String) { s.push_str("!") }
fn main() {
let mut s = String::from("a");
let l = len(&s);
println!("len={}", l);
push_exclaim(&mut s);
println!("{}", s);
}
2.4 切片与字符串
讲解:切片是对集合的只读视图,不拥有数据;字符串切片按字节索引,需保证落在 UTF-8 字符边界。
示例:完整可执行的切片演示
ini
fn main() {
let a = [1, 2, 3, 4];
let slice = &a[1..3];
println!("{:?}", slice);
let s = String::from("hello");
let r: &str = &s[0..2];
println!("{}", r);
}
三、类型与数据结构
3.1 基本类型、元组、数组与切片
讲解:Rust 的标量与复合类型具备显式类型与固定大小;数组在栈上分配、长度固定;切片为只读视图。
示例:完整可执行的类型演示
rust
fn main() {
let i: i32 = -1;
let f: f64 = 3.14;
let b: bool = true;
let c: char = '中';
let tup: (i32, &str) = (7, "a");
let (n, s) = tup;
let arr: [i32; 3] = [1, 2, 3];
let slice: &[i32] = &arr[..];
println!("i={}, f={}, b={}, c={}", i, f, b, c);
println!("tup=({}, {})", n, s);
println!("arr={:?}", arr);
println!("slice={:?}", slice);
}
3.2 String 与 &str
讲解:String 可变且拥有堆数据;&str 为只读借用的字符串视图;两者互补使用。
示例:完整可执行的字符串演示
rust
fn main() {
let mut s = String::from("hi");
s.push_str("!");
let r: &str = &s;
println!("String={}", s);
println!("&str={}", r);
}
3.3 结构体与实现
讲解:struct 定义数据结构,impl 块中可添加关联函数与方法;方法的第一个参数为接收者 &self 或 &mut self。
示例:完整可执行的结构体方法演示
rust
struct Point { x: i32, y: i32 }
impl Point {
fn new(x: i32, y: i32) -> Self { Self { x, y } }
fn norm(&self) -> f64 { ((self.x.pow(2) + self.y.pow(2)) as f64).sqrt() }
}
fn main() {
let p = Point::new(3, 4);
println!("{}", p.norm());
}
3.4 枚举与模式匹配
讲解:enum 可表达代数数据类型;match 覆盖所有分支并支持解构与条件守卫。
示例:完整可执行的枚举匹配演示
rust
enum Shape { Circle(f64), Rect { w: i32, h: i32 } }
fn area(s: Shape) -> f64 {
match s {
Shape::Circle(r) => 3.14159 * r * r,
Shape::Rect { w, h } => (w * h) as f64,
}
}
fn main() {
let c = Shape::Circle(2.0);
let r = Shape::Rect { w: 3, h: 4 };
println!("{}", area(c));
println!("{}", area(r));
}
3.5 Option 与 Result
讲解:Option 表示可空值,促使显式处理缺失情况;Result 表示可能出错的操作,结合 match 或 ? 传播错误。
示例:完整可执行的 Option 与 Result 演示
rust
fn find(v: &[i32], x: i32) -> Option<usize> {
for (i, n) in v.iter().enumerate() {
if *n == x { return Some(i); }
}
None
}
fn main() {
let v = vec![1, 2, 3];
match find(&v, 2) {
Some(i) => println!("found at {}", i),
None => println!("not found"),
}
let ok = "42".parse::<i32>();
let err = "x".parse::<i32>();
match ok { Ok(n) => println!("ok {}", n), Err(e) => println!("error {}", e) }
match err { Ok(n) => println!("ok {}", n), Err(e) => println!("error {}", e) }
}
四、函数、控制流与闭包
4.1 函数与返回值
讲解:函数返回值以尾表达式形式出现,无需 return;类型推断在参数位置较保守,需显式类型。
示例:完整可执行的函数演示
rust
fn add(a: i32, b: i32) -> i32 { a + b }
fn main() {
let r = add(2, 3);
println!("{}", r);
}
4.2 控制流
讲解:if 是表达式可赋值;for 基于迭代器;loop 可构建无限循环并通过 break 退出。
示例:完整可执行的控制流演示
ini
fn main() {
let x = if true { 1 } else { 2 };
println!("{}", x);
for i in 0..3 { println!("{}", i); }
let mut n = 0;
while n < 3 { n += 1; println!("{}", n); }
let mut k = 0;
loop {
k += 1;
if k == 2 { break; }
}
println!("{}", k);
}
4.3 match 与 if let / while let
讲解:match 要覆盖所有可能分支;if let、while let 简化对特定模式的处理。
示例:完整可执行的模式演示
scss
fn main() {
let v = Some(1);
match v {
Some(n) if n > 0 => println!("positive"),
Some(_) => println!("non-positive"),
None => println!("none"),
}
if let Some(n) = v { println!("{}", n); }
let mut it = Some(0);
while let Some(n) = it {
if n == 2 { it = None; } else { it = Some(n + 1); }
println!("{}", n);
}
}
4.4 闭包与捕获
讲解:闭包可自动推断参数与返回类型,并按需以不可变/可变/按值捕获环境变量。
示例:完整可执行的闭包演示
ini
fn main() {
let mut n = 0;
let mut f = |x: i32| { n += x; n };
println!("{}", f(2));
println!("{}", f(3));
let v = vec![1, 2, 3];
let s: i32 = v.iter().map(|x| x * 2).sum();
println!("{}", s);
}
五、模块、泛型、生命周期与并发
5.1 模块与包结构
讲解:mod 定义子模块,pub 决定对外可见性;use 简化路径;二进制 crate 入口为 main.rs。示例以内联模块展示。
示例:完整可执行的模块演示
rust
mod utils {
pub fn greet(name: &str) -> String { format!("Hello, {}", name) }
}
fn main() {
let s = utils::greet("Rust");
println!("{}", s);
}
5.2 Trait 与泛型
讲解:Trait 描述行为接口;泛型结合 trait bounds 实现约束;零成本抽象避免运行时开销。
示例:完整可执行的 trait 与泛型演示
rust
trait Area { fn area(&self) -> f64; }
struct Circle { r: f64 }
struct Rect { w: f64, h: f64 }
impl Area for Circle { fn area(&self) -> f64 { 3.14159 * self.r * self.r } }
impl Area for Rect { fn area(&self) -> f64 { self.w * self.h } }
fn sum<T: std::ops::Add<Output=T> + Copy>(a: T, b: T) -> T { a + b }
fn print_area<T: Area>(s: &T) { println!("{}", s.area()); }
fn main() {
let c = Circle { r: 2.0 };
let r = Rect { w: 3.0, h: 4.0 };
print_area(&c);
print_area(&r);
println!("{}", sum(1, 2));
println!("{}", sum(1.5, 2.5));
}
5.3 生命周期
讲解:生命周期参数声明引用至少存活到返回值使用完;编译器借助省略规则自动推断多数场景。
示例:完整可执行的生命周期演示
rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let a = String::from("abcd");
let b = String::from("xyz");
let r = longest(&a, &b);
println!("{}", r);
}
5.4 集合与迭代器
讲解:集合位于标准库;迭代器链支持惰性计算与组合操作;HashMap 提供键值存储与借用访问。
示例:完整可执行的集合与迭代器演示
rust
use std::collections::HashMap;
fn main() {
let v = vec![1, 2, 3, 4];
let even_sum: i32 = v.iter().filter(|n| *n % 2 == 0).sum();
println!("{}", even_sum);
let mut m = HashMap::new();
m.insert("a", 1);
m.insert("b", 2);
if let Some(x) = m.get("a") { println!("{}", x); }
for (k, v) in &m { println!("{} {}", k, v); }
}
5.5 智能指针与并发
讲解:Rc<T> 在单线程中实现共享所有权;并发下用 Arc<T> 提供原子引用计数,搭配 Mutex<T> 进行互斥访问;线程通过 spawn 创建并在 join 等待完成。
示例:完整可执行的智能指针与并发演示
rust
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let a = Rc::new(String::from("x"));
let b = Rc::clone(&a);
println!("{} {}", a, b);
let c = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..4 {
let c2 = Arc::clone(&c);
handles.push(thread::spawn(move || {
let mut n = c2.lock().unwrap();
*n += 1;
}));
}
for h in handles { h.join().unwrap(); }
println!("{}", *c.lock().unwrap());
}
5.6 代码质量与测试
讲解:cargo fmt 统一代码风格;cargo clippy 静态诊断建议;测试框架内置,使用 #[test] 标记。
示例:在同一文件中包含测试与可执行入口
rust
#[cfg(test)]
mod tests {
fn add(a: i32, b: i32) -> i32 { a + b }
#[test]
fn it_works() { assert_eq!(add(2, 2), 4); }
}
fn main() {
println!("run `cargo test` to execute tests");
}
常用命令:
bash
cargo fmt
cargo clippy
cargo test