环境搭建与第一个 Rust 程序

环境搭建与第一个 Rust 程序
XIU今日教学目标
- 完成 Rust 工具链(rustup、rustc、cargo)安装并验证版本。
- 安装并熟悉 RustRover IDE:创建项目、运行程序、查看项目结构。
- 理解 Rust 项目基本结构:
Cargo.toml、src/main.rs。 - 编写第一个
Hello, world!程序,体验编译型语言工作流。 - 理解 Rust 语言的设计哲学:安全、高性能、无畏并发,以及它为什么值得学习。
为什么要学 Rust?
在正式动手之前,先聊聊 Rust 到底好在哪里。
编译器是你最好的搭档
Rust 的编译器不仅仅帮你找错误,它还会主动推荐正确的写法。比如下面这段代码,启动了一个新线程引用当前线程的变量:
1 | let name = "xiu".to_string(); |
这段代码隐含着线程不安全的访问——当前线程持有的变量 name 可能在新线程使用之前就被释放,发生 use-after-free 错误。Rust 编译器不仅能在编译期检测出这个错误,告诉你原因”may outlive borrowed value”,还会进一步推荐你加入 move 关键字来解决。它甚至给出 rustc --explain E0373 命令让你查看详细的错误解释。
这种体验,就好像你旁边坐着一个和蔼可亲的大牛,在孜孜不倦地帮你审阅代码。一旦你适应了,就很难离开。
性能与表达力兼得
Rust 编译出的程序运行速度和 C/C++ 是一个级别的,同时它的使用体验又像 Python/TypeScript 这样的高级语言,表达能力一流。截止 2021 年,主流互联网公司纷纷把 Rust 纳入主力语言——Dropbox 用 Rust 重写文件同步引擎、Discord 用 Rust 重写状态服务。Discord 原先使用 Golang 的状态服务,一来消耗大量内存,二来在高峰期因为垃圾回收导致巨大延迟,换成 Rust 后不仅性能提升,还让代码重构变得举重若轻。
无畏并发
Rust 的所有权系统让你在写多线程代码时,编译器会帮你检查数据竞争问题。其他语言中被标榜为实践典范的并发手段,在 Rust 这里只不过是一种并发工具。Rust 提供了从 atomics 到 Mutex、Semaphore、Channel,再到 actor model 的全套并发原语,同时还能保证并发安全。
学习曲线:先苦后甜
Rust 被公认是一门难学的语言。它的核心难点是变量的所有权和生命周期——这是几乎所有其他编程语言都未曾涉及的领域。但一旦迈过这段艰难的思维转换期,其他的知识点就是所有权和生命周期概念在不同领域的具体使用。
学习 Rust 的方法可以总结为精准学习 + 刻意练习:深挖一个个表层知识点,回归底层基础知识的本原,再一层层往上构建知识体系。就像撒一层土,夯实,再撒一层。
💡 类比理解:
rustc是 Rust 的”翻译官”,把 Rust 代码翻译成机器能运行的二进制文件cargo是 Rust 的”项目经理”,负责管理依赖、编译、测试、运行rustup是”版本管家”,负责安装、切换、升级 Rust 版本
如果没有安装,访问 https://www.rust-lang.org/zh-CN/tools/install 下载 rustup-init.exe,按提示安装即可。安装完成后重新打开 PowerShell 再验证。
在 UNIX 系统下(如 macOS/Linux),可以直接运行:
1 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
这会在你的系统上安装 Rust 工具链。
安装与启动 RustRover
- 从 JetBrains 官网下载并安装 RustRover(学生可申请免费教育授权)。
- 打开 RustRover,第一次启动会让你选择主题和导入设置,按喜好选择即可。
创建第一个 Rust 项目
按照以下步骤操作:
- 点击菜单栏
File → New Project。 - 在左侧选择
Rust。 - 右侧配置:
- Name:输入项目名,比如
day01_hello - Location:选择项目存放路径
- Toolchain:选择系统已安装的 rustup(一般会自动检测到)
- Standard library:勾选
Download via rustup,这样以后可以跳转到标准库源码 - Project template:选择
Binary,表示生成一个可执行程序(有main函数)
- Name:输入项目名,比如
- 点击
Create,稍等片刻,项目就创建好了
💡 类比理解:选择
Binary就像告诉工厂”我要生产一台能直接开的汽车”;如果选择Library,则是”我要生产一批零件,给别人装配用”。
认识项目结构
创建后,左侧 Project 视图(按 Alt+1 可显示/隐藏)会看到:
1 | day01_hello/ |
Cargo.toml:相当于项目的”身份证 + 采购清单”,里面写项目名称、版本、作者、依赖等信息。它符合 TOML 格式。src/main.rs:程序的入口文件,相当于”大门”。程序从这里开始执行。target/:编译后生成的文件都在这里。刚开始没有,第一次编译后出现。
运行程序
有三种方式运行:
方式 1:点击绿色三角按钮
- 打开
src/main.rs,在fn main()左侧会出现一个绿色的小三角 - 点击它,选择
Run 'Run day01_hello',程序就会编译并运行 - 运行结果会出现在底部
Run工具窗口(按Alt+4可切换)
方式 2:右键菜单
- 在
src/main.rs文件上右键,选择Run 'day01_hello'
方式 3:Terminal 手动执行
- 打开底部 Terminal 标签(按
Alt+F12打开/关闭) - 输入:
1
cargo run
1 |
|
💡 类比理解:
main函数就像一本书的”第一章第一页”,读者(操作系统)打开书后,自动从这里开始读。
Rust 的整体语法偏 C/C++ 风格:
- 函数体用花括号
{}包裹 - 表达式之间用分号
;分隔 - 访问结构体的成员函数或变量使用点
.运算符 - 访问命名空间或对象的静态函数使用双冒号
::运算符 - 可执行体的入口函数是
main()
💡 初学者提示:现在不需要深入理解宏的原理,只要记住:带
!的是宏,不带的是函数。宏的原理会在 Day 29 详细讲解。
println! 是宏,不是普通函数
注意 println! 后面有个感叹号 !。在 Rust 中,带 ! 的是宏(macro),不是普通函数。
1 | fn main() { |
- 普通函数调用:
函数名(参数) - 宏调用:
宏名!(参数)
💡 类比理解:普通函数就像一台固定程序的咖啡机,只能做固定口味的咖啡;宏更像一台”能根据你的指令现场改装自己的咖啡机”,它在编译时把代码展开成具体的函数调用。Rust 支持声明宏和过程宏(包含派生宏、属性宏、函数宏),
println!是用macro_rules!定义的声明宏。
Rust 是 AOT 编译型语言
AOT = Ahead Of Time,也就是”提前编译”。你写的 Rust 代码需要先经过编译器处理,生成机器码,然后才能运行。
这和 Python、JavaScript 等解释型语言不同——它们通常是边读边执行。
💡 类比理解:AOT 编译就像把整本外语书提前翻译成中文书,读者读中文书时很快;解释型语言就像请一个翻译官在边上逐句翻译,灵活性高但运行时慢一些。
Rust 的核心语言特点
通过第一个程序,我们可以感受到 Rust 的一些基本特点:
使用 cargo 管理项目:类似 Node.js 的 npm、Golang 的 go,用来做依赖管理和开发过程中的任务管理(编译、运行、测试、格式化等)。
强类型语言,但支持类型推导:写代码时的直观感受和写脚本语言差不多。编辑器中安装了 rust-analyzer 插件后,变量的类型会自动提示出来。
变量默认不可变:如果要修改变量的值,需要显式地使用
mut关键字。这符合最小权限原则,有助于写出健壮的代码。绝大多数代码都是表达式:
if/while/for/loop都会返回一个值,函数最后一个表达式就是返回值,这和函数式编程语言一致。支持宏编程:很多基础功能如
println!()都被封装成宏,让开发者写出简洁的代码。支持面向接口编程和泛型编程。
有非常丰富的数据类型和强大的标准库。
Cargo.toml 关键字段
打开 Cargo.toml,你会看到类似下面的内容:
1 | [package] |
[package]:表示下面是关于这个包本身的配置name:包名,通常也是生成的可执行文件名version:版本号,遵循”语义化版本”规范,格式为主版本.次版本.修订号edition:Rust 语言版本。当前常用"2021",就像 Java 的 Java 8、Java 17 一样,不同 edition 语法略有差异[dependencies]:依赖列表。以后要使用第三方库时,就写在这里
💡 类比理解:
Cargo.toml就像一份餐厅的菜单和营业执照——菜单(dependencies)告诉顾客你能吃到什么菜,营业执照(package)说明你叫什么名字、是什么版本。一个 Rust 项目也被称为一个 crate,crate 可以是可执行项目,也可以是一个库。
Cargo 工作流
开发时的典型工作流如下:先用 cargo check 快速检查代码能否编译(不生成二进制文件,速度最快),如果有错就修改代码;确认无误后用 cargo build 编译,或直接用 cargo run 编译并运行。三者形成一个高效的开发循环。
第一个实用 Rust 程序:网页抓取
Hello World 太简单了,让我们来写一个稍有实际意义的程序——通过 HTTP 请求 Rust 官网首页,把获得的 HTML 转换成 Markdown 保存起来。用 JavaScript 或 Python 可能只需要十多行代码,我们看看 Rust 怎么处理。
首先,用 cargo new scrape_url 生成一个新项目。在 Cargo.toml 中加入依赖:
1 | [dependencies] |
然后,在 src/main.rs 中编写代码:
1 | // 引入标准库的 fs 模块,用于文件操作 |
运行 cargo run,在一段略微漫长的编译后,程序开始运行:
1 | Fetching url: https://www.rust-lang.org/ |
当前目录下会生成一个 rust.md 文件,内容就是 Rust 官网主页的 Markdown 版本。Bingo!第一个 Rust 程序运行成功!
从这个例子中,我们可以感受到:
- Rust 虽然是强类型语言,但编译器支持类型推导,写代码的直观感受和脚本语言差不多
use关键字可以简化对命名空间内部函数或数据类型的引用- 错误处理使用
Result<T, E>类型,unwrap()是简化写法,只关心成功的结果
⚠️ 避坑指南:第一次编译会比较慢,因为 cargo 需要下载并编译所有依赖。后续修改代码后重新编译会快很多,因为 cargo 只会重新编译改动过的部分。
常见错误 / 避坑指南
1. 在错误的目录运行 cargo
1 | error: could not find `Cargo.toml` in `.` or any parent directory |
原因:你不在包含 Cargo.toml 的目录中。
解决:cd 到项目根目录再执行。
2. 链接器缺失
1 | error: linker `link.exe` not found |
原因:Windows 上缺少 MSVC 构建工具。
解决:安装 Visual Studio Build Tools,勾选”C++ 桌面开发”工作负载。
3. RustRover 红色波浪线不消失
原因:rust-analyzer 还在索引项目,或依赖尚未下载完成。
解决:等待右下角进度条完成;如果卡住,点击 Cargo 工具窗口的刷新按钮。
4. 编译时间过长
原因:第一次编译需要下载并编译所有依赖 crate。
解决:这是正常的。后续增量编译会快很多。可以使用 cargo check 代替 cargo build 来快速检查代码。
💡 类比理解:第一次编译就像第一次做一道复杂的菜——你要去超市买齐所有食材和调料。之后只要食材还有库存,再做就快了。
🔒 安全视角延伸
缓冲区溢出:C/C++ 的阿喀琉斯之踵
在正式踏入 Rust 的安全世界之前,让我们先了解一个困扰 C/C++ 程序员数十年的梦魇——缓冲区溢出(Buffer Overflow)。
什么是缓冲区溢出攻击?
程序在运行时会在栈上为局部变量分配固定大小的内存空间(缓冲区)。如果程序向缓冲区写入数据时不检查长度,攻击者就可以输入超出缓冲区容量的数据,多余的字节会覆盖相邻的内存区域——包括栈帧中存储的返回地址。
当函数执行完毕、CPU 准备返回时,它会读取被覆盖的返回地址,跳转到攻击者指定的位置执行恶意代码(shellcode)。这就是经典的栈溢出攻击(Stack Smashing)。
C 语言 vs Rust:代码对比
下面是一段典型的 C 语言漏洞代码:
1 | // vuln.c — 演示缓冲区溢出漏洞(请勿在生产环境使用) |
strcpy 函数会将 name 的所有字节拷贝到 buf 中,不检查目标缓冲区的大小。如果 name 超过 8 字节,多出的数据就会覆盖栈帧中的返回地址。
等价的 Rust 代码则是完全安全的:
1 | // safe.rs — Rust 版本,编译运行均安全 |
Rust 在两个层面阻止缓冲区溢出:
- 编译期:所有权和借用检查器确保不存在悬垂指针和越界访问的模式。
- 运行期:数组/切片访问会进行边界检查(bounds check)。如果索引越界,程序会立即 panic 并安全退出,而不是默默写入非法内存。
安全税:微小的代价,巨大的回报
有人可能会担心边界检查带来的性能开销。实际上,现代 CPU 的分支预测器对边界检查的命中率极高(绝大多数访问都是合法的),开销通常只有 1-2 条指令。这就像超市入口的安检——大多数顾客都不会触发警报,但它能在关键时刻阻止危险物品进入。
Rust 用这微小的运行时开销,彻底免疫了缓冲区溢出、越界读写、use-after-free 等整类内存安全漏洞。根据微软安全响应中心的数据,约 70% 的安全漏洞属于内存安全问题。Rust 从语言层面消灭了这些漏洞的生存土壤。
📖 延伸阅读:OWASP Buffer Overflow — 了解更多关于缓冲区溢出攻击的原理与防护策略。
课后实验作业
作业 1:创建并运行 Hello World
- 在 RustRover 中创建新项目
day01_hello - 修改
main.rs,让程序输出:1
2Hello, Rust!
I am learning Rust from the Rust Book.
1 | 3. 在 Terminal 中分别执行 `cargo build`、`cargo run`、`cargo check`,观察差异 |
运行方式及差异说明:
cargo check:只检查代码能否编译,不生成可执行文件,速度最快cargo build:编译并生成target/debug/day01_hello.execargo run:编译(如果需要)并直接运行,最方便
作业 2 答案
修改后的 Cargo.toml:
1 | [package] |
在 Windows 上,执行 cargo build 后,可执行文件位于:
1 | target/debug/day01_hello.exe |
可以直接在 Terminal 中输入 ./target/debug/day01_hello.exe 运行。
作业 3 答案
1 | // day01_hello/src/main.rs |
作业 4 答案(大实验种子)
Cargo.toml:
1 | [package] |
src/main.rs:
1 | // pi_agent/src/main.rs |
今日小结
- Rust 是一门兼顾性能、安全、表达力的系统级编程语言,编译器会像大牛一样帮你审阅代码并推荐修复方案。
rustup、rustc、cargo是 Rust 的三大核心工具。- RustRover 是 JetBrains 出品的 Rust IDE,能大幅提升开发效率。
Cargo.toml是项目的”身份证 + 采购清单”,src/main.rs是程序入口。cargo check快速检查,cargo build编译,cargo run编译并运行。- 我们今天种下了
pi_agent大实验的种子,后面的每一天都会往里面添砖加瓦。 - Rust 的学习曲线虽然陡峭,但只要迈过所有权的思维转换期,就能体会到”越用越享受”的编程体验。






