mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
mobile wallpaper 5
6323 字
17 分钟
The Golden Rust语言 01 — 概述、类型系统、控制流与函数
2026-08-09

本文基于 清华邓博士的 B 站视频 整理,时长约 2 小时 55 分钟。


零、这堂课在讲什么#

这是”Golden Rust”系列的第一讲。它不讲具体的 Rust 语法细节,而是建地基——解释 Rust 为什么是这样设计的。核心回答三个问题:

  1. Rust 在嵌入式领域为什么有前途?(生态优势 > 安全优势)
  2. Rust 的 trait 系统解决了 C/C++ 的什么根本问题?(组合 vs 继承)
  3. 理解 Rust 需要哪些底层认知?(栈/堆/内存布局/编译器哲学)

如果你刚接触 Rust,这堂课会帮你建立一个”为什么这么学”的框架。如果你写 C/C++,后半部分对栈和堆的解释会让你重新审视自己每天都在用的概念。


一、Rust 的三个核心优势(为什么它能进入嵌入式?)#

传统认知是:“Rust = 内存安全语言”。但在这堂课中,主讲人把安全排在了第三位。他给出的排序是:

高性能 > 抽象能力 > 内存安全

1.1 高性能:零运行时,像 C 一样快#

嵌入式系统最底层是裸机——没有操作系统那一层缓冲。你的代码直接跑在硬件上。这意味着什么?

┌─────────────────────────┐
│ Python / JavaScript │ ← 有运行时/GC,嵌入式无法承受
├─────────────────────────┤
│ C++ │ ← 有运行时开销(虚表/异常/RTTI)
├─────────────────────────┤
│ C / Rust │ ← 零运行时,编译后几乎一对一映射为机器指令
└─────────────────────────┘

“嵌入式中间没有那么多 OS 层,全是裸机。所以必须要一个像 C 语言一样快的东西,小的运行时,基本上就是你写的代码叠加一点点东西就能够跑。”

Rust 和 C 在这里站在同一条起跑线上。C++ 则因为虚函数表、异常处理、RTTI 等机制产生的额外运行时开销,在资源极端受限的嵌入式场景中几乎没有立足之地。

1.2 抽象能力:解决嵌入式生态的碎片化#

这才是主讲人眼中 Rust 最闪亮的点。

嵌入式世界极度碎片化:STM32 的库和 ESP32 的库完全不兼容,8 位机和 32 位机的编程模型完全不一样。“不同的开发板,里面的芯片结构不一样,管脚不一样,IO 设备不一样,指令架构不一样——特别散。”

Rust 的 trait 系统提供了一种统一的抽象层。官方有专门的 Embedded Working Group 负责定义接口标准,然后:

┌──────────────────────────────────────┐
│ 上层生态(15万个 crate) │ ← 依赖 trait 接口,不依赖具体硬件
├──────────────────────────────────────┤
│ 官方 trait 抽象层(embedded-hal 等) │ ← Rust Embedded WG 制定
├──────────────────────────────────────┤
│ 厂商实现:STM32 HAL │ ESP32 HAL │ nRF │ ← 各厂商/社区对接同一套 trait
└──────────────────────────────────────┘

“抽象一旦做好,官方给出的标准抽象做好,大家往上靠就完了。靠上了以后,大家可以互通有无了。”

他举了一个 C 语言中”从来不会发生”的例子:在 ESP32 嵌入式开发板上运行一个 Lisp 解释器。在 C 语言里,移植一个 Lisp 解释器到特定嵌入式平台要处理大量平台相关的依赖——而在 Rust 里,确认包支持 no_std,加一行 Cargo.toml 依赖,就能编译运行。

对比 C 语言:

“C 的很多生态的很多包都是各自为战的,无法融会贯通搞在一起。在 Rust 里面,各行各业的标准库都给好了,你直接用,一站式解决。“

1.3 内存安全:消除一整类 Bug#

把未来的问题挪到编译期。这在后面第五节会详细展开。


二、为什么 C 无法形成这样的生态?#

这是整堂课花了最长时间论证的核心命题。

2.1 根源:C 缺少”标准数据结构”#

设想你要设计一个通用的 String 类型。随着使用者增多,以下问题会逐一浮现:

维度C 的做法Python 的做法Rust 的做法
用什么编码存储?没规定,自己定统一用 4 字节/字符UTF-8(变长,节省空间)
修改串是原地改还是生成新串?没规定能 copy 就 copy(牺牲性能)两种都有(&str 只读,String 可写)
分割函数返回什么容器?各自实现返回新的 list返回迭代器(零拷贝)
容器元素是副本还是引用?各自实现副本取决于你选 &str 还是 String

“你表面上从逻辑上想用一个人类可用的字符串,在微观层面上如果真的要考虑内存,要考虑这么多事情。有巨量的细节需要考虑,而且很多问题没有通用解法。”

这就是组合爆炸:这些问题的每个维度都是正交的,组合起来产生指数级的可能性。C 语言直接放弃了——让每个库的作者自己决定。结果就是:

  • 库 A 造了自己的 Vector
  • 库 B 造了自己的 Vector
  • 库 A 的 Vector 和库 B 的 Vector 不兼容
  • 你要同时用 A 和 B,就得手写数据结构转换代码

“真正的让生态繁荣起来,你 A 做的包和 B 做的包要想接在一起,最重要的是数据结构表达的统一。大家操作的都是同样一套内存表达,这个事情才能玩在一起。”

Python 靠内置 list/dict/str 做到了这一点(所以生态庞大),但代价是性能(比 C 慢 300 倍,在嵌入式无法使用)。Rust 则通过内置标准数据结构 + trait 系统做到了同样的统一性,但零运行时开销。

2.2 Rust 的解法:组合爆炸解决组合爆炸#

“Rust 是我见到的目前来说唯一一个直面这些问题的语言。如果我们在语言层面上就特别倾向于用组合爆炸的表达方式——很多小函数,每个小函数只做一小部分转换,然后串在一起形成组合——那么也许它就可以解决这些精细的组合爆炸的需求。”

这体现在 Rust 代码特有的链式调用风格:

// Rust 的典型风格:每一步都是一个小转换
let result = values
.iter() // 获取迭代器
.map(|x| x * 2) // 每个元素乘以2
.filter(|x| *x > 10) // 过滤
.collect::<Vec<_>>(); // 收集成 Vec

每步都是一个独立的小操作,可以任意替换、组合。这种风格在 C 语言中需要用多次独立的函数调用和临时变量来表达,失去了简洁性。


三、Trait:用”维度”代替”继承”#

3.1 香蕉与大猩猩#

“面向对象的语言的问题在于,他总是附带着他所需要的隐含环境。你想要一个香蕉,但得到的是一个拿着香蕉的大猩猩,而其后还有整个丛林。”

这句话不是主讲人原创的——它出自 Joe Armstrong(Erlang 之父),收录于《Coders at Work》(2009年)。它精确地描述了继承的问题:当你从类 A 继承时,你继承了 A 的全部——所有成员变量、所有方法。你无法”只要香蕉”。

继承能很好地表达天然就是层级结构的关系(比如 GUI 组件:按钮是窗口的子类),但现实中大部分情况是:

“四不像——它又像猫,又像老虎。最佳的表达应该是把猫的一部分特性拿过来,把老虎的一部分特性拿过来,叠加起来是它。“

3.2 用维度理解 Trait#

主讲人提出了一个非常直观的理解方式:

能看(维度)
人 ● │ ● 机器人
───────────┼───────────→ 能跑(维度)
│ ● 特斯拉汽车

struct = 实体(真正占内存的东西)。 人、机器人、特斯拉汽车,它们在内存中可以完全不像。

trait = 维度(一种”能力标签”)。 “能看”是一个维度——人和机器人在这个维度上都在正象限。“能跑”是另一个维度——人和特斯拉在正象限,但普通机器人可能在负象限。

“生态本质是官方控制了 trait,提供了一堆 trait,大家底下随便换就行了。上面的生态去依赖 trait,不要依赖于具体的结构。这就是抽象的核心——做结构跟 trait 之间的依赖,而不是结构和结构之间的依赖。”

映射到编程语言:在 C++ 里,trait 最接近”只有纯虚函数的抽象类”——但这个类比很蹩脚。Rust 的 trait 远比 C++ 的纯虚类强大,它天生支持组合,不需要也不支持继承。


四、语言的三个横切面#

“整个 Rust 语言就是三层结构。元能力、抽象能力、具象能力。没有第四层。它非常克制,不会乱加没用的特性。“

4.1 元能力(宏):自己定义语法#

println! 后面那个感叹号 ! 代表它是一个宏。宏的本质是代码生成器——在编译期把你的简写展开成完整代码。

// 你写的
println!("x = {}", x);
// 编译器展开后(大致相当于)
io::_print(format_args!("x = {}\n", x));

更强大的宏可以让你在 Rust 中嵌入其他语言的语法:

  • Slint(23k+ stars):在 Rust 中嵌入声明式 UI 语法,编译为原生 GUI,支持树莓派/STM32 等嵌入式平台
  • SQLx(17k+ stars):在 Rust 中直接写 SQL,编译期连接数据库验证语法正确性
// SQLx:原生 SQL,编译期验证
let countries = sqlx::query!(
"SELECT country, COUNT(*) as count FROM users GROUP BY country WHERE organization = ?",
organization
)
.fetch_all(&pool)
.await?;
// countries[0].country, countries[0].count — 编译期就确定类型

4.2 抽象能力(Trait/泛型)#

这是第三部分讲的内容——trait 系统决定了 Rust 能有多强的表达力和生态潜力。

4.3 具象能力:类型与值#

视频的后半段开始进入具体的类型系统。核心原则是:Rust 的类型必须精确,没有任何模糊空间。

基本数值类型:

在 C 语言里,int 到底是几个字节?C 标准只说 long ≥ int ≥ short,具体长度由编译器和平台决定。想精确控制就必须写 int32_t(还需要 #include <stdint.h>)。

Rust 直接把这个问题从源头消灭:

类型含义
i8 / i16 / i32 / i64 / i128有符号整数,位宽写在类型名里
u8 / u16 / u32 / u64 / u128无符号整数
f32 / f64浮点数
usize / isize和当前 CPU 架构宽度一致(32位机器=32位,64位机器=64位)
char4 字节,完整覆盖 Unicode(包括 emoji)
booltruefalse

usize 的存在是因为有时你需要表达”和机器字长一样大的数字”——比如指针大小、数组索引、内存偏移量。如果你的代码要同时在 32 位和 64 位平台上跑,用 usize 而不是 u32u64

Rust char ≠ C char。 C 的 char 是 1 字节,只能存 ASCII。Rust 的 char 是 4 字节,存的是完整的 Unicode 标量值——中文、日文、emoji 全在里面,一个 char 一个字,没有乱码问题。主讲人的评价是:“他觉得这个代价是可以付得起的。”

数字字面量也可以很精确:

let x = 42; // 默认 i32
let y = 42_i64; // 显式指定为 i64
let z = 0xff_u8; // 十六进制 u8
let big = 1_000_000; // 下划线分隔,跟写 1000000 完全一样

下划线纯粹是为了人眼可读——三位一组,就像财务数字写逗号一样。

4.4 类型推导:看起来像脚本,实际是强类型#

let x = 42; // 你没写类型,但编译器知道 x 是 i32

“这种写法感觉上好像像咱们 Python 里面写脚本一样,你都不需要声明类型。但实际上是强类型语言——他后面都帮你填上了。”

这对应 C++ 的 auto,但 Rust 的类型推导能力更强。在 VS Code 里装了 rust-analyzer 插件后,把鼠标悬停在变量上就能看到推导出的类型——“相当于他帮你写了这个小代码。”

“原来你都得自己写这个,现在不用写了,让他自动帮你推导,这多香啊。”

Rust 官方有个网页版 playground(play.rust-lang.org),可以直接在浏览器里写代码运行。但主讲人推荐配本地 VS Code——“你写的程序一复杂以后,它的类型是什么?我跟你说,Rust 里面玩的就是类型。对类型要非常的敏感。他玩的就是类型,他把所有的信息全都堆到类型里面。“

4.5 宏再深入:println! 展开与卫生红#

在第四部分的元能力基础上,视频后半段做了更具体的演示。

println! 是宏,不是函数。 你写 println!("x = {}", x),编译器第一步就是把这个宏展开。展开后的代码比原来长得多——println 本身消失了,变成了一串对标准库输出函数的调用。cargo expand 命令可以随时查看展开结果,“去掉红的魔法,看看它是什么。”

宏的 ! 后面可以跟三种括号:

println!("hello"); // 小括号——看起来像函数调用
vec![1, 2, 3]; // 中括号——看起来像数组
println!{"hello"}; // 大括号——看起来像代码块

“你用什么完全取决于你想在这个地方表达什么。像函数一样调用就用小括号,像一段代码块就用大括号——这是自由的。”

卫生红(Hygienic Macro): “卫生”的意思是像函数一样——内部定义的变量不会”污染”外部作用域。println! 内部不管展开成什么样,都不会跟你外面的变量名冲突。这是 Rust 宏区别于 C 语言 #define 宏的根本特征——C 的宏只是文本替换,会产生各种意想不到的变量名冲突。

4.6 Rust 与 C 的关系:C 是后盾#

“Rust 跟 C 的接口极其好。它可以自动从 C 头文件中生成 Rust 代码,你直接就可以用了。有 C 作为保底——如果有些能力官方只提供了 C 库,没法用 Rust 怎么办?自己手动生成一个就完了。”

这回答了”如果生态还不够怎么办”的问题——Rust 不会让你无路可走。它的 FFI(Foreign Function Interface)跟 C 的对接极其顺畅。


五、编译器的”安全区”模型#

5.1 把 Bug 消灭在编译期#

“Rust 把所有的潜在问题全都堆积在编译器。如果编译过了,你基本上大概率就成功了。他把未来的问题全都挪到现在——你在写代码的时候就要面对它们。”

┌────────────────────────────────┐
│ 逻辑上正确的代码(理想边界) │
│ ┌──────────────────────────┐ │
│ │ Rust 编译器允许的"安全区" │ │ ← 宁可错杀,不放过
│ │ (编译器通过的,全部正确) │ │
│ └──────────────────────────┘ │
│ ↑ 这之间的灰色地带 │
│ 有些代码逻辑没问题, │
│ 但编译器不让你写 │
└────────────────────────────────┘

代价是受限制——“我们写的时候需要更加谨慎才能过”。但好处是:

“你经过了这个语言严谨的训练以后,你再去写 C 和 C++,你能看到里面很多漏洞——‘哎,这个内存他怎么没考虑到?那个怎么没考虑到?‘有点入奢易,由奢入俭难。“

5.2 算术溢出:C vs Rust#

一个小例子说明 Rust 的严谨性:

// C:默默截断,没有任何提示
int16_t x = 300 * 300 * 300; // 溢出,静默截断为低 16 位
// Rust:编译不通过!
let x: i16 = 300 * 300 * 300; // error: attempt to multiply with overflow

你必须显式告诉编译器你要怎么处理溢出:

let x: i16 = (300_i16).saturating_mul(300).saturating_mul(300); // 溢出就顶到头 32767

saturating_* 是”饱和运算”的一种——溢出就取最大值。还有 wrapping_*(回绕到最小值继续算)、checked_*(返回 Option)等。这就是 Rust 的组合方式:每种溢出策略是一个独立的小函数,你想用哪种就链哪种。

类型转换同样必须显式。在 C/C++ 里,int8_t 传给需要 uint32_t 的函数会自动隐式转换——“默默的发生,你不知道。” Rust 不允许:

let y: i8 = 20;
let x: u32 = y; // 编译错误!i8 不能自动变 u32
let x: u32 = y as u32; // 显式转换,用 as 关键字

“在 Rust 里面很多地方不能囫囵吞枣。你说多少就是多少。” as 是 Rust 的关键字,用于显式类型转换——和 saturating_add 等运算级转换互补。


六、栈与堆#

6.1 为什么栈上的东西必须是定长的?#

这是理解 Rust 所有权系统的前提。 主讲人从 RISC-V 汇编的角度给出了最底层的解释。

struct A { int field1; int field2; };
struct A a;
int b = 3;
int c = 5;

编译为 RISC-V 汇编后:

sw a0, -28(s0) # a.field1 → 固定偏移 -28
sw a1, -24(s0) # a.field2 → 固定偏移 -24
sw zero, -20(s0) # b = 3 → 固定偏移 -20
addi a2, zero, 5 # c = 5 → 固定偏移 -16

“每一个局部变量,在微观上看起来都是一堆固定的偏移。基于栈顶指针 SP 这个基准去访问你所有数据结构的成员。这就是栈必须要定死的原因——它要能用一个固定的偏移去访问。”

如果栈上出现了变长数组,整个偏移量体系就崩溃了:要访问下面的变量,你首先得知道上面那个变长数组的实际长度——这个值只有运行时才能确定。每次变量访问都要做额外的算术运算,在函数调用的热路径上完全不可接受。

C 语言提供了 alloca() 在栈上分配动态内存,但这是一个危险的设施——分配的内存随函数返回自动释放,但如果大小不可控导致栈溢出,就是灾难。Rust 选择完全不在安全代码中暴露这种能力。

6.2 String vs &str:胖指针的两种形态#

这是 Rust 中最直观展示”栈和对分离”的例子。

&str:轻量级引用(16 字节)

栈上(16 字节):
┌──────────────────┬──────────────────┐
│ ptr (8B) │ len (8B) │
│ 指向数据的地址 │ 数据长度 │
└──────┬───────────┴──────────────────┘
堆/全局区:
┌──────────────────────┐
│ h e l l o │ ← 只读,不可增删
└──────────────────────┘

String:拥有所有权的字符串(24 字节)

栈上(24 字节):
┌──────────┬──────────┬──────────┐
│ ptr (8B) │ len (8B) │ cap (8B) │
│ 堆数据指针│ 当前长度 │ 已分配容量 │
└────┬─────┴──────────┴──────────┘
堆:
┌─────────────────────────────┐
│ h e l l o │ (空闲...) │ ← 可增长(len ≤ cap)
└─────────────────────────────┘

String&str 多了一个 cap(capacity)字段。这意味着当你想往 String 里追加字符时,如果 len < cap,直接写入即可;如果 len == cap,则自动重新分配一块更大的堆内存。

“在 C 里,str 的结尾用 \0 来表达结束——这是一个非常简单朴素的方法。但在 Rust 里不这么干,要显式地把长度存下来。C 不存长度的原因是存了就有最大长度限制,而且指针变厚了。但 Rust 付出额外 8 字节的代价,换来了 O(1) 的长度查询和二进制安全。”

切片操作是 &str 最强大的用法。同一个堆数据可以被多个 &str 从不同位置、不同长度引用——它们只是”视角”不同,数据本身没有任何拷贝:

String "Hello, Rust!" 在堆上:
H e l l o , R u s t !
0 1 2 3 4 5 6 7 8 9 10 11
&str[0..5] → "Hello" (ptr→0, len=5) ← 零拷贝切片!
&str[7..11] → "Rust" (ptr→7, len=4)
&str[0..12] → 整个串 (ptr→0, len=12)

⚠️ 注意:str 是 UTF-8 变长编码,切片时如果切到了某个多字节字符的中间位置,程序会 panic。“切到一个字符的一半是没意义的。” Rust 在运行时会检查切片边界是否落在有效的 UTF-8 字符边界上——这也是它”严谨性”的体现。


七、控制流与函数:一切皆表达式#

视频后半段的核心主题可以浓缩为一句话:在 Rust 中,几乎一切都是表达式。

7.1 表达式 vs 语句#

但在进入控制流之前,有一个更基础的语法习惯需要先适应:

7.0 名字在前,类型在后#

let x: i32 = 10; // Rust: 名字 x,类型 i32 在后面
// vs
int x = 10; // C: 类型 int 在前面,名字 x 在后面

“你表面上看它只是个约定习俗的问题。但随着你体会深了以后,你会感觉到名字在前面更合理。”

C 语言的类型声明经常出现”名字被夹在中间”的混乱情况:

int *x; // 类型在前,名字在后 — OK
int x[3]; // 名字在中间,数组标记在后面 — 开始乱了
int (*f)(int); // 名字被包裹在中间 — 完全乱了

“表达数组时 [3] 又在后面,表达指针时 * 又在前面——乱套。在 Rust 里面不存在这种歧义性,它全在后面。”

名字、类型、值这三个东西哪个最重要?名字最重要——因为后续所有操作都靠名字来引用。类型定一次就够了,值是运行时才知道的。

“名字是给人读的。名字优先放前面,越琢磨越合理。”

现代语言在这点上已经达成一致:Go、Swift、OCaml、Haskell 都是名字在前。Rust 的抽象层(trait 系统)直接借鉴自 OCaml。C 的这种”类型在前”是早期设计选择,C++ 为了兼容 C 只能延续。

7.1 表达式 vs 语句#

表达式(Expression)语句(Statement)
有返回值?✅ 有❌ 没有
能传参?✅ 能作为函数参数❌ 不能
能赋值?✅ 能放等号右边❌ 不能
例子5 + 3if true { 1 } else { 2 }let x = 1;return;
结尾不加分号加分号

“分号结尾是在结束一个表达式。一个东西加分号结束,它就不是表达式了——它不能传参,不能赋值。不加分号,它就是一个表达式,可以用在任何需要值的地方。”

验证一个东西是不是表达式的简单方法:看看它能不能作为参数传给函数。

7.2 if 是表达式#

let x = if n < 10 { n } else { 10 };

C 的 if 是纯控制流,不能返回值。Rust 把 if 变成了表达式。Python 也有类似写法(a = 30 if b < 20 else 50),但 Python 的 if 表达式和 if 控制流是两套语法。Rust 统一了——你写的 if 既是控制流也是表达式。

7.3 loop 是表达式#

let result = loop {
if done { break 42; } // break 带值
};

“他在原来 C 语言的基础上扩展了这个能力——循环里可以 break 出来一个返回值。”

break 还可以带标签一次性跳出多层嵌套循环。

7.4 裸大括号也是表达式#

let x = {
let a = compute();
a + 1 // 最后一行不加分号 → 整个块的返回值
};

大括号创建新作用域,C 里做不到返回值。“你可以在里面做很多准备工作,最后一下不加分号返回出去。很自然。“出圈就释放——下节课讲所有权时会变得非常重要。

7.5 函数也是表达式#

fn add_one(x: i32) -> i32 {
x + 1 // 不加分号 = 返回值
// 等价于: return x + 1;
}

“写时间长了就会发现不加 return 更舒服。return 一般用在提早返回。”

最后一行加分号 → 编译器自动插入空元组 () 作为返回值(相当于 C 的 void)。

7.6 for 循环:语法糖#

for x in 1..5 { println!("{x}"); }
// 1..5 展开后 = Range { start: 1, end: 5 }

“从写作层面写简单的 1..5,从理解层面按复杂的理解——去完糖以后就好理解了。Rust 里所有运算符都可以去糖。“

7.7 没有重载,没有默认参数——故意的#

“C++ 既支持 overloading,又支持隐式类型转换,又支持默认参数——三个混在一起就会形成无比难受的歧义性。你传一个 U8 进去,到底走哪个版本?走第一个也成立,走第二个也成立,走第三个也成立。没有人知道 C++ 到底是怎么工作的。”

Rust 的选择:函数名不能重复、没有隐式转换、没有默认参数。需要重载 → 后面用 trait 做,一种完全不同的、无歧义的机制。

7.8 变量遮蔽(Shadowing)#

let a = true; // a: bool
let a = "hello"; // a: &str — 全新的 a
let a = 42_i32; // a: i32 — 又一个全新的 a

“根本就不是同一个变量,只是恰好三个名字重名——就像两个中国人名字相同,两个不同的中国人。“出圈后外层变量重新可见。不限制类型——可以拿完全不同类型的变量去遮蔽。


八、用 Rust 训练思维#

“很多人说,你就算学了 Rust 以后不去用 Rust,你也会对其他的语言有一个新的理解。”

Rust 把所有在其他语言中隐性存在的概念——所有权、生命周期、借用规则——全部提到了明面上

“在其他语言里面这些都是潜规则。在 Rust 中全是明面上的规则。你训练好这个思维方式以后,你再去写 C 和 C++ 的时候,你就很不自然——‘哎,这个内存他怎么没考虑到?那个怎么没考虑到?‘“


引用索引#

书籍/文档:

  • 《Comprehensive Rust》(Google,4 天课程)— 本课使用的教材 - 链接
  • 《The Rust Programming Language》(官方 Rust Book)— “有点长,有中文版” - 链接
  • Rust Course — “比较适合国人口味,简洁不废话” - 链接
  • 《Coders at Work》(Peter Seibel,2009)— “香蕉与大猩猩”比喻的原始出处 - Joe Armstrong 访谈

工具/仓库:

  • crates.io — Rust 包仓库,约 15 万个包 - 链接
  • Slint(23k+ stars)— 声明式 GUI,支持嵌入式 - 链接
  • SQLx(17k+ stars)— 编译期 SQL 检查 - 链接
  • cheats.rs — Rust 语法速查表 - 链接
  • embedded-hal — 嵌入式硬件抽象层 trait 标准 - 链接
  • Embassy(9.6k stars)— 嵌入式异步运行时 - 链接

概念出处:

  • “香蕉与大猩猩” — Joe Armstrong,《Coders at Work》(2009)
  • “为什么只有 C++ 开发者喜欢实现自己的 string?” — 知乎讨论,视频中引用解释 C 生态碎片化
  • UTF-8 变长编码 — 类似 Huffman 编码原理:常见字符用短编码,生僻字符用长编码

原视频#

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

The Golden Rust语言 01 — 概述、类型系统、控制流与函数
https://www.trtyr.top/posts/golden-rust-01-overview-types-control-flow/
作者
特让他也让
发布于
2026-08-09
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录