资源地址

Rust 从入门到进阶:13 个核心知识点一篇吃透(含可运行示例)

这篇文章基于我本地的 Rust 学习项目整理,按 src/bin/01~13 的顺序,把高频知识点统一串起来,适合做学习路线图和面试前复习清单。

一、项目说明与运行方式

项目结构(核心):

  • src/bin/01_variables.rs
  • src/bin/02_data_types.rs
  • src/bin/03_functions.rs
  • src/bin/04_control_flow.rs
  • src/bin/05_ownership.rs
  • src/bin/06_structs.rs
  • src/bin/07_enums_match.rs
  • src/bin/08_collections.rs
  • src/bin/09_modules_packages.rs
  • src/bin/10_error_handling.rs
  • src/bin/11_generics.rs
  • src/bin/12_traits.rs
  • src/bin/13_lifetimes.rs

运行示例:

cargo run --bin 01_variables
cargo run --bin 05_ownership
cargo run --bin 13_lifetimes

检查所有示例是否可编译:

cargo check --bins

二、Rust 架构图与关系图

1)Rust 编译与运行架构图

Rust Source Code

Parser AST HIR

Type Check

Borrow Checker

MIR Optimize

LLVM Backend

Native Binary

OS Runtime

这个图可以理解为:Rust 在编译阶段就把类型和借用问题尽量解决掉,最终输出本地机器码,运行时不依赖 GC。

2)Rust 核心特性关系图

Ownership

Borrow

Move

Drop

Immutable Ref

Mutable Ref

Lifetime

No Dangling Ref

Type System

Struct Enum

Generics

Traits

Error Handling

Result

Option

panic

你可以把它记成两条主线:

  • 内存安全主线:Ownership -> Borrow -> Lifetime
  • 抽象复用主线:Type System -> Generics -> Traits

三、13 个核心知识点

01. 变量(Variables)

核心点:

  • let 默认不可变。
  • let mut 可变。
  • const 必须标注类型,且值需在编译期可确定。
  • Shadowing(遮蔽)可用同名变量重新绑定,并可改变类型。
  • 支持解构赋值。

示例:

let x = 10;
let mut y = 20;
y += 5;

const MAX_POINTS: u32 = 100_000;

let x = x + 1;
let x = x.to_string();

let (a, b) = (1, 2);

易错点:

  • 把不可变变量当可变变量修改会直接编译报错。

02. 数据类型(Data Types)

核心点:

  • 标量类型:i32f64boolchar
  • 复合类型:元组 (T1, T2, ...)、数组 [T; N]
  • 切片 &[T] 是借用视图,不拥有数据。
  • 字符串分 &str(切片)和 String(可增长堆字符串)。

示例:

let tup: (i32, f64, char) = (500, 6.4, 'Z');
let arr: [i32; 4] = [10, 20, 30, 40];
let slice: &[i32] = &arr[1..3];

let s1: &str = "hello";
let s2: String = String::from("world");

03. 函数(Functions)

核心点:

  • 参数和返回值类型都要显式写。
  • Rust 是表达式语言:函数最后一个无分号表达式可作为返回值。
  • 代码块本身也是表达式。
  • 闭包可快速定义匿名函数逻辑。

示例:

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

let v = {
    let base = 10;
    base * 2
};

let multiply = |x: i32, y: i32| x * y;

04. 流程控制(Control Flow)

核心点:

  • if / else if / else
  • if 可作为表达式返回值。
  • loop 可配合 break value 返回值。
  • while 条件循环。
  • for 常用于遍历数组和范围。
  • match 强制穷尽匹配。
  • if let 适合只关心一个模式的简写场景。

示例:

let parity = if n % 2 == 0 { "even" } else { "odd" };

let doubled = loop {
    counter += 1;
    if counter == 5 {
        break counter * 2;
    }
};

match grade {
    'A' => println!("excellent"),
    _ => println!("keep learning"),
}

05. 所有权与借用(Ownership & Borrowing)

这是 Rust 最关键的一章。

核心规则:

  1. 每个值有且只有一个所有者。
  2. 同一时刻只能有一个所有者。
  3. 所有者离开作用域,值被释放。

核心点:

  • String 赋值/传参默认 move。
  • &T 是不可变借用,不转移所有权。
  • &mut T 是可变借用,同一时刻只能有一个。
  • .clone() 是深拷贝(有成本)。
  • 字符串切片 &str 是典型借用返回值。

示例:

fn takes_ownership(s: String) { println!("{s}"); }
fn borrows_str(s: &str) { println!("{s}"); }

fn first_word(s: &str) -> &str {
    match s.find(' ') {
        Some(index) => &s[..index],
        None => s,
    }
}

高频结论:

  • Rust 用“编译期约束”替代运行时 GC,换来更强的性能可预测性和内存安全。

这一节最容易混淆的 6 个概念(建议收藏)

概念 发生了什么 是否转移所有权 典型场景
move 把值的控制权交给新变量/函数参数 let b = a;String 这类堆对象)
borrow (&T) 只读借用值 读取数据但不修改
mutable borrow (&mut T) 可写借用值 原地修改集合、结构体字段
clone() 深拷贝数据,得到新所有者 否(原值仍可用) 需要保留原值且传递副本
Copy 按位复制(轻量) 否(语义上像复制) i32boolchar 等栈上简单类型
lifetime 描述引用之间谁活得更久 不涉及所有权转移 返回引用、结构体持引用字段

常见误区 1:clone 不是“借用”,而是“创建一份新数据”,会有内存和性能成本。
常见误区 2:Copyclone 不同,Copy 是编译器隐式行为,通常用于小而简单的值类型。

一个对比示例:

let a = String::from("hello");
let b = a;          // move,a 失效
// println!("{a}"); // 编译报错

let c = b.clone();  // 深拷贝,b 和 c 都可用
println!("{b} {c}");

let x = 10;         // i32 是 Copy 类型
let y = x;          // 复制,不是 move
println!("{x} {y}");

可变借用规则示例:

let mut v = vec![1, 2, 3];
let r1 = &mut v;
// let r2 = &mut v; // 同一作用域内再借一个 &mut 会报错
r1.push(4);
println!("{:?}", r1);

06. 结构体(Structs)

核心点:

  • 命名字段结构体:业务建模主力。
  • 元组结构体:有名字但字段无名。
  • 单元结构体:常用作标记类型。
  • impl 中可以写关联函数和方法。
  • Self 表示当前类型。
  • 支持结构体更新语法 ..old

示例:

#[derive(Debug)]
struct User {
    username: String,
    active: bool,
    sign_in_count: u64,
}

impl User {
    fn new(username: &str) -> Self {
        Self { username: username.to_string(), active: true, sign_in_count: 1 }
    }
}

07. 枚举与模式匹配(Enum + Match)

核心点:

  • 枚举变体可以携带不同类型数据。
  • match 可直接解构变体数据。
  • Option<T> 取代空指针语义(Some / None)。
  • 可用 match guard 增加额外条件判断。

示例:

enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        Some(v) => Some(v + 1),
        None => None,
    }
}

08. 常见集合(Collections)

核心点:

  • Vec<T>:动态数组,支持 push/get/迭代/可变迭代
  • String:UTF-8 可变字符串,常用 push/push_str/format!
  • HashMap<K, V>:键值表,常用 insert/get/entry().or_insert()

示例:

let mut numbers = Vec::new();
numbers.push(10);

let mut scores = HashMap::new();
scores.entry(String::from("Carol")).or_insert(88);

易错点:

  • vec[index] 越界会 panic!get(index) 更安全。

09. 包、Crate、模块(Package / Crate / Module)

概念速记:

  • package:由 Cargo.toml 定义。
  • crate:编译单元(lib 或 bin)。
  • module:crate 内代码组织和可见性边界。

核心点:

  • mod 定义模块。
  • pub 控制对外可见性。
  • use 缩短路径书写。
  • crate:: 从当前 crate 根开始的绝对路径。
  • pub(crate) 仅 crate 内可见。

示例:

mod math {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    pub(crate) fn square(n: i32) -> i32 { n * n }
}

use crate::front_of_house::hosting;

10. 错误处理(Error Handling)

核心点:

  • 可恢复错误:Result<T, E>
  • ? 用于错误向上传播。
  • 不可恢复错误:panic!(谨慎使用)。
  • 可自定义错误类型并实现 Display + Error
  • From 可打通错误自动转换链路。

示例:

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

实践建议:

  • 业务代码优先 Result,减少 panic!

11. 泛型(Generics)

核心点:

  • 泛型函数:复用算法。
  • 泛型结构体:复用数据结构。
  • impl<T> + 特定类型 impl 可组合。
  • trait bound(如 T: PartialOrd)约束能力边界。

示例:

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

12. Trait(特征)

核心点:

  • trait 类似行为接口。
  • trait 可定义必需方法和默认方法。
  • 可为不同类型实现同一个 trait。
  • 参数可写 &impl Trait 或泛型 bound。
  • 返回 impl Trait 可隐藏具体类型。

示例:

trait Summary {
    fn summarize(&self) -> String;
    fn short(&self) -> String { String::from("(read more...)") }
}

fn notify(item: &impl Summary) {
    println!("{}", item.summarize());
}

13. 生命周期(Lifetimes)

核心点:

  • 生命周期用于描述“引用之间的有效期关系”,不是延长对象寿命。
  • 函数返回引用时,常需显式生命周期参数。
  • 结构体持有引用时,必须标注生命周期。
  • 'static 表示整个程序期间都有效。

示例:

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() >= y.len() { x } else { y }
}

struct ImportantExcerpt<'a> {
    part: &'a str,
}

高频结论:

  • 生命周期的本质是让编译器证明“不会出现悬垂引用”。

四、建议学习路线(实战导向)

  1. 01~04:语法与控制流,快速建立 Rust 语感。
  2. 05:所有权反复练习到“看代码就能判断 move/borrow”。
  3. 06~09:数据建模与工程化组织。
  4. 10~13:错误处理、抽象能力和生命周期,进入中级门槛。

五、Rust 新手常见坑

  • 忘记引用类型导致 move 后变量失效。
  • 同时存在多个可变借用。
  • String&str 混用导致类型不匹配。
  • match 分支不穷尽。
  • 对越界索引使用 [] 而非 get()

六、结语

如果你正在系统学习 Rust,这 13 个文件就是一条完整的主线:

  • 从语法到内存模型;
  • 从数据结构到模块化组织;
  • 从错误处理到泛型、trait、生命周期。

建议每个知识点都做三件事:

  1. 先运行示例。
  2. 再手改参数触发编译错误。
  3. 最后脱离提示手写一遍。

这样学习 Rust 的效率会明显更高。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐