第 1 课:认识 Rust 与开发环境 ------ 装好工具链,跑通第一个程序
预计时间:60-75 分钟 | 难度:⭐⭐ | 前置:会一门编程语言、本机能装软件
1.1 为什么是 Rust?这节课要解决什么问题
先回答一个你会反复被问、也最该先想清楚的问题:学 Rust 到底图什么?
Rust 是一门系统级编程语言,2006 年起源于 Mozilla(为解决 Firefox 的内存安全与并发 bug),2015 年发布 1.0,后由独立的 Rust Foundation 治理。它有两个其他语言很难同时给你的承诺:
① 性能 ≈ C / C++(无 GC、无运行时、零成本抽象)
② 内存安全 = 编译器保证(没有空指针、悬垂指针、数据竞争,
且不需要垃圾回收器)
这几乎是语言设计里的"不可能三角"(快、安全、好写,通常三选二),Rust 通过一套独特的所有权系统,在编译期就把内存错误拦下来,而不是等运行期崩溃或靠 GC 兜底。
今天 Rust 已经长成基础设施级语言,典型的真实使用者:
| 领域 | 例子 |
|---|---|
| 浏览器引擎 | Firefox(Servo 的继任者) |
| 操作系统 | 微软 Windows 内核组件、Linux 内核模块、Android 部分组件 |
| 云端/CDN/网络 | AWS、Cloudflare、字节跳动等服务端与边缘计算 |
| 开发者工具 | ripgrep、cargo 自身生态、deno、tauri |
| 区块链/Web3 | 大量底层链实现 |
| 嵌入式/移动 | 本课程的"跨平台共享核心"就是典型移动场景 |
那本课程(移动端共享核心)为什么值得用 Rust?对比着看才说得清:
同一份业务逻辑(网络/数据/存储/算法)
↓ 交给 Rust 一次写完
↓ 编译成: Android .so / iOS xcframework / macOS dylib / Windows dll / wasm
↓ iOS/Android 原生 App 只画 UI,各自调同一份核心
- 网络请求、JSON 解析、SQLite、加解密、流式处理这类代码平台无关,正是 Rust 的主场;
- 双端不再"同一需求写两遍",规则一致性、测试成本、维护成本都大幅下降;
- 性能好且无 GC:不会有 GC 暂停,也方便跨线程/跨 FFI 边界搬运数据;
- 交叉编译工具链成熟:一套代码能稳定地产出 iOS/Android/桌面/Web 各自的包。
一句话记住本课立场:Rust 是"库/核心"型语言------业务核心放在 Rust,界面留在各端原生。(界面若用 Flutter/RN 则另有更省事的桥,本课程只讲 iOS/Android 原生 UI + Rust 核心这条线。)
1.2 Rust 与常见语言横向对比
对比不是"谁更好",而是帮你建立坐标系:什么场景下选 Rust 最划算。
| 维度 | C / C++ | Rust | Go | Kotlin / Swift |
|---|---|---|---|---|
| 内存安全 | 手动(易错) | 编译期保证 | GC | GC / ARC |
| 运行时 / GC | 无 | 无 | 有 GC | 有 |
| 与 C 的性能 | 基准 | ≈ C | 略低 | 低于 C |
| 并发安全 | 难 | 编译期防数据竞争 | goroutine 简单 | 靠框架约定 |
| 学习曲线 | 陡 | 陡(前期所有权有门槛) | 平 | 平 |
| 跨端移动产物 | 能但难 | 很顺(本课主线) | gomobile 生态较弱 | 各自平台 |
| 移动端现状 | 少 | 中(基础设施向) | 极少 | Kotlin=安卓/Swift=iOS |
几个容易被问到的"那为啥不用别人":
- 为什么不用 C/C++ 写核心? 跨端共享逻辑 C/C++ 也能做,但内存错误是常态(野指针、缓冲区溢出),团队养两个原生栈的人来维护一个 C 核心很不划算。
- 为什么不用 Go? Go 好写,但有 GC 且移动端交叉编译/FFI 绑定生态远不如 Rust;做移动库(
.so/framework)历史上很别扭。 - 为什么不用 Kotlin Multiplatform? KMP 的共享代码确实能编 iOS,但它是"Kotlin 生态内的共享";若你想让同一份逻辑还服务桌面/Web/wasm,且要 C 级性能与确定性内存,Rust 的自由度更高。两者可以并存:KMP 共享 UI 侧逻辑,Rust 放性能与系统级核心。
- 为什么不用 Flutter? Flutter 是把 UI 也一起共享;本课程前提是"UI 保持 iOS/Android 原生",所以 UI 层不共享,只共享 Rust 核心。
1.3 工具链全家桶:rustup、rustc、cargo 与周边
先认识这几个词,后面每天都要打交道:
┌─────────────────────────────────────────────────────┐
│ rustup 工具链管理器(类似 nvm/pyenv) │
│ ├─ 管理 stable / beta / nightly 三个 channel │
│ ├─ 按项目锁定版本、添加交叉编译 target │
│ └─ 管理组件:rustc / cargo / rustfmt / clippy ... │
│ rustc 编译器本体 │
│ cargo 构建 + 包管理 + 测试(类似 npm/pip 合体)│
│ rustfmt 代码格式化(`cargo fmt`) │
│ clippy Rust 官方 linter(`cargo clippy`) │
│ rust-analyzer IDE 智能提示(走 LSP 协议) │
└─────────────────────────────────────────────────────┘
你需要知道的版本节奏(也是面试常问的常识):
- Rust 每 6 周发一个 stable 版本 ,版本号形如
1.90.0;本课写作时用你安装时的最新 stable 即可,无需死记版本号。 - channel :日常只用
stable。beta用于预演,nightly用于尝鲜不稳定特性。商业项目 99% 锁stable。 - edition(版次) :指语言"大版本代际":
2015 / 2018 / 2021 / 2024。它解决"语言升级不破坏老代码"的问题------同一份工程显式声明用哪个 edition 编译。2025 年 2 月起新项目默认2024,本课所有例子都基于它。edition 详解放到第 10 课(Cargo 工程化),现在只需知道 Cargo.toml 里那行edition = "2024"是啥意思。
1.4 安装与验证
macOS(本课程演示主力系统)
bash
# 方式一:官方脚本(推荐)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 安装完成后,脚本会提示把 cargo 环境写入 shell 配置
# 重新打开终端(或执行 source "$HOME/.cargo/env")后验证
- 脚本会同时装好
rustc、cargo、rustfmt、clippy、rust-analyzer及本地文档。 - 用 Homebrew 也可(
brew install rustup),但官方脚本是文档默认、最不容易出岔子。 - Apple Silicon(M 系列)默认宿主目标为
aarch64-apple-darwin,无需手动配置。
Windows
- 到 https://rustup.rs 下载运行
rustup-init.exe(按提示选默认项即可)。 - 关键坑 :MSVC 工具链需要一个 C++ 链接器。若没装过,先去装 Visual Studio Build Tools (勾选"使用 C++ 的桌面开发"工作负载),否则
cargo run会报找不到link.exe。 - 完成后新开终端验证。
Linux
bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 部分发行版需先安装 build-essential / clang 等基础编译工具
验证是否装好
bash
rustc --version # 例:rustc 1.9x.0 (xxxx-xx-xx)
cargo --version # 例:cargo 1.9x.0
rustup show # 查看当前生效的工具链与安装的 target
rustup update # 日常升级 stable 用这条
能看到三个命令输出版本号,环境就绪。
(网络受限时)配置国内镜像
若 rustup update 或拉 crates 很慢,可配置镜像(非必需,可选步骤):
bash
# 写入 ~/.zshrc 或 ~/.bashrc(以 rsproxy 为例)
export RUSTUP_DIST_SERVER=https://rsproxy.cn
export RUSTUP_UPDATE_ROOT=https://rsproxy.cn/rustup
# crates.io 走镜像需改 ~/.cargo/config.toml(见下文"改配置"一段)
crates 镜像的具体写法放在第 10 课(Cargo 依赖管理)里给全量示例,现在不影响装环境。
IDE:VS Code + rust-analyzer(本课默认)
- 装 VS Code;
- 扩展里搜 rust-analyzer 安装(这是当前社区标准,靠 LSP 提供跳转/补全/错误提示);
- 打开工程目录,底部状态栏会出现 rust-analyzer,输入时就会有编译级诊断。
备选:JetBrains 系用 RustRover / CLion + Rust 插件,老手也可用 Neovim/Helix 接 rust-analyzer。
💡 小知识:rust-analyzer 只做"提示",不替代
cargo build的真实编译;以cargo输出为准。
⚠️ 安装常见坑清单:
- 重开终端后仍提示
cargo: command not found:多为 PATH 未加载,执行source "$HOME/.cargo/env",或重开终端窗口。 - Windows 报
link.exe not found:缺 VS C++ 生成工具,见上文"关键坑"。 - 在 WSL/容器里装:记得先装系统的 gcc/make 等基础工具链。
- 路径别带中文/空格 (尤其 Windows):
cargo new建工程时用英文目录最省心。
1.5 第一个程序:hello,走一遍 cargo 全流程
1.5.1 新建项目
bash
cargo new hello
cd hello
cargo new 会生成如下结构(这就是一个标准 Rust 项目的最小形态):
hello/
├── .gitignore # 自动忽略 target/(cargo 已为你配好)
├── Cargo.toml # 项目"户口本":元信息 + 依赖声明
└── src/
└── main.rs # 唯一源码入口(程序从 main 开始跑)
💡
target/目录(编译产物)要到第一次 build 后才出现,它相当于缓存+输出目录,可以随时删,删了下次重新编译即可。
1.5.2 逐行读 Cargo.toml
toml
[package]
name = "hello" # 包名:决定库名/二进制名,只能小写字母数字下划线
version = "0.1.0" # 语义化版本
edition = "2024" # 语言版次(见 1.3)
[dependencies] # 第三方依赖写这里,现在为空
[package] 是项目元信息;[dependencies] 之后会装着 reqwest、serde 这些 crate(crate ≈ 别人写好的库/包,是 Rust 世界里"依赖包"的叫法)。现在还不用管,第 10 课会展开。
1.5.3 读 main.rs 并跑起来
rust
fn main() {
println!("Hello, world!");
}
先别管语法细节,跑起来看流程:
bash
cargo build # 只编译:生成 target/debug/hello
cargo run # 编译 + 运行(日常最常用)
cargo check # 只做类型检查,不生成产物(最快的"体检")
cargo run 的输出长这样,每一行都有含义:
Compiling hello v0.1.0 (.../hello) ← 正在编译
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.3s
Running `target/debug/hello` ← 实际执行的命令
Hello, world!
- 编译出的二进制在
target/debug/hello,你可以绕过 cargo 直接运行它:./target/debug/hello; - debug 模式(默认)编译快、带调试信息但未优化 ;发布优化用
cargo build --release(产物在target/release/),第 10 课细讲 profile; cargo run也支持给程序传参,但参数要写在--之后:cargo run -- 参数1 参数2(写命令行工具时常用)。
1.5.4 改一改:第一个属于自己的程序
rust
fn main() {
// 这行是注释:给人类看的,编译器会忽略
let app_name = "小灵 AI 助手核心"; // 声明一个变量,let 声明、默认不可变
println!("你好,{}!", app_name); // {} 是占位符,会被后面的值替换
println!("这是 Rust 跨平台课程的第 1 个程序");
}
输出:
你好,小灵 AI 助手核心!
这是 Rust 跨平台课程的第 1 个程序
💡 你可能会问:
let声明的变量为什么默认不能改?这就是 Rust 的"默认不可变"设计,正是它配合所有权消灭了一大类 bug。第 2 课马上细讲。
1.5.5 故意写错一次:认识 Rust 的报错(非常重要)
Rust 编译器的报错以"贴心"著称,但你要先学会怎么读。故意写一行类型不对的代码:
rust
fn main() {
let answer: i32 = "42"; // 声明 answer 是整数,却赋了字符串
println!("{answer}");
}
运行 cargo run,会得到类似输出(可运行验证):
error[E0308]: mismatched types
--> src/main.rs:2:24
|
2 | let answer: i32 = "42";
| ^^^^ expected `i32`, found `&str`
|
= note: expected type `i32`
found type `&str`
报错信息的标准读法(本课程此后所有报错都这么读):
error[E0308] ← 错误码(E + 数字),可上网搜这个码
mismatched types ← 一句话总结错误类型
--> src/main.rs:2:24 ← 文件:行:列,精确定位
2 | ... ← 出错那行原文(带 ^^^^ 指示具体位置)
= note: ... ← 编译器进一步解释
把类型改对即可:let answer: i32 = 42;。后面几乎每课都会让你"故意写错再看报错",这是学 Rust 最高效的姿势之一------报错本身就是最好的老师。
1.6 println! 与格式化输出第一课
println! 后面的 ! 表示它是一个宏(macro)而不是普通函数。宏的威力后面会讲,现在只记三个观察:
rust
fn main() {
let x = 42;
let name = "Rust";
// 1) 多个占位符按顺序填充
println!("{name} 值 x = {x},乘以 2 = {}", x * 2);
// 2) {:?} / {:#?}:调试输出,数组、结构体都靠它
let nums = [1, 2, 3];
println!("nums = {:?}", nums); // 单行紧凑
println!("nums = {:#?}", nums); // 多行美化(之后写代码打印结构体全靠它)
// 3) {n} 按编号复用同一个参数
println!("{1} 和 {0} 和 {1}", "A", "B"); // 输出:B 和 A 和 B
}
输出:
Rust 值 x = 42,乘以 2 = 84
nums = [1, 2, 3]
nums = [
1,
2,
3,
]
B 和 A 和 B
两个规则先记下:
{}要求类型实现Display(给人看的格式);{:?}要求实现Debug(调试格式)。大多数基础类型两个都实现好了;自定义的结构体默认不实现 ,打印前要写#[derive(Debug)],第 6 课会用到。- 中文/Unicode 在源码里直接用没问题------Rust 源码默认 UTF-8。
💡 系统性的格式化(对齐、精度、进制、填充)留到第 2 课,这里够用即可,别贪多。
1.7 常用命令与文档习惯(本课查文档方法论)
从这门课开始养成"遇事查官方文档"的习惯,它比任何教程都全:
bash
cargo doc --open # 打开当前项目所有依赖的本地文档
rustup doc --book # 打开本地《The Rust Programming Language》(Rust Book)
rustup doc --std # 打开本地标准库文档
在线资源(配合本课使用):
- doc.rust-lang.org/std:标准库文档,查函数签名与用法最权威;
- docs.rs:第三方 crate 文档(每个 crate 都有,带例子);
- crates.io:crate 搜索与发布平台(相当于 Rust 版 npm);
- 中文问题可搜中文社区/博客,但对"语法细节"优先信官方文档与编译器报错。
💡 推荐工作流:报错 → 先自己读报错信息 →
cargo doc/docs.rs 查 API → 再不行才搜网。你会比多数人进步快。
1.8 📝 动手练习
本节练习都应在 cargo new 出的独立项目里完成,参考实现放在 code/01-basic-env/(写作时同步给出),先自己写再看。
- 装环境 :完成 1.4 全部安装与验证命令,把
rustc --version输出贴进终端截图/笔记。 - 建项目 :
cargo new greeting,把main.rs改成打印三行自我介绍(如 名字 / 所在城市 / 今天是星期几),用cargo run跑通。 - 体验 check :同一项目里分别跑
cargo check、cargo build、cargo run,对比哪个最快、哪些命令产生target/debug/greeting文件。 - 练习读报错 :故意改出两种错误------①
let age: u32 = -1;(类型不匹配);② 把println!漏掉!写成println(...)(找不到函数/宏)。分别把报错码(如 E0308、E0425)记下来,并修好它们。 - 格式化练习 :用
{:#?}打印数组[1, 2, 3],并用编号占位{0}写一行"复读机"式输出(例如把同一个值打印两次)。 - 查文档 :用
rustup doc --book打开本地 Rust Book,翻到第一章,和本课对照着各读 10 分钟。 - (选做)版本实验 :把
Cargo.toml的edition从2024改成2015,cargo run是否报错?试着解释(提示:edition 决定语言特性集合,留第 10 课验证答案)。
验收门禁 :cargo new 后不改任何配置,仅修改 src/main.rs,能让程序打印出含中文的两行以上内容;能说出 cargo run 报错信息里"错误码 + 文件行列"分别在哪。
✅ 本节小结
- Rust = 系统级语言:性能≈C,内存安全由编译器保证,无 GC;
- 本课程目标架构:业务逻辑(网络/数据/存储)写在 Rust,iOS/Android 只做 UI 壳,靠跨平台编译产出双端包;
- 工具链 =
rustup(管理器)+cargo(构建/依赖)+rustc+rustfmt/clippy/rust-analyzer; - 标准工程结构:
Cargo.toml+src/main.rs,cargo new/run/build/check是最高频命令; - 报错信息三要素:错误码
E0xxx+ 定位文件:行:列+ 解释 note,读错位是第一技能; println!的{}(Display)、{:?}(Debug)、{n}(编号占位)三种基本用法。
下一课预告 :第 2 课《基础语法:变量、类型、函数与控制流》------把 let/mut、所有基础数据类型、表达式与语句、if/loop/while/for 一次性讲透,每讲配可运行例子。基础篇每课环环相扣,建议按顺序来。