第1章 Rust入门与生态:从历史到第一个可运行的程序

Rust 是一门由 Mozilla Research 主导开发、于 2015 年发布 1.0 稳定版的系统级编程语言。它的诞生源于一个长期困扰 C/C++ 社区的难题:如何在保证内存安全的前提下,不牺牲性能与控制力。Rust 的设计目标可以概括为“安全、并发、务实”——它通过所有权(Ownership)、借用(Borrowing)和生命周期(Lifetime)三大核心机制,在编译期消除数据竞争、空指针、悬垂指针等内存错误,同时不引入垃圾回收(GC)带来的运行时开销。本章作为 45 天精通 Rust 的第一课,将带你完成从理解 Rust 的定位、安装工具链,到使用 Cargo 创建并运行第一个项目的完整闭环。

Rust 入门知识框架与工具链链路 三大设计目标 • 内存安全(无 GC) • 无畏并发(数据竞争) • 零成本抽象 • 性能媲美 C/C++ 核心机制 • 所有权(Ownership) • 借用(Borrowing) • 生命周期(Lifetime) • 模式匹配与代数类型 工具链 • rustup(版本管理) • cargo(构建/依赖) • rustc(编译器) • rustfmt / clippy Cargo 创建项目流程 cargo new hello_world → 进入目录 → 编辑 main.rs → cargo build → cargo run 项目结构 hello_world/ ├── Cargo.toml(清单) └── src/main.rs(源码) main 函数与 println! 宏 fn main() { ... } println!("Hello, {}!", name); 宏:编译期展开,非函数调用

1.1 Rust 的历史与设计目标

Rust 最早由 Graydon Hoare 于 2006 年在 Mozilla 开始作为个人项目,2009 年 Mozilla 正式赞助,2015 年 5 月 15 日发布 1.0 稳定版。它的诞生背景非常具体:Firefox 浏览器中的 CSS 引擎 Servo 需要一种既能提供高性能、又能避免 C++ 中常见内存错误(如缓冲区溢出、释放后使用)的语言。Rust 的设计目标并非“取代 C++”,而是为系统编程提供一种更安全、更现代的选择。

Rust 的核心设计目标可以归纳为以下四点:

  • 内存安全:通过所有权和借用检查器,在编译期杜绝空指针、悬垂指针、双重释放等问题,不需要垃圾回收器。
  • 无畏并发:编译器在编译期检查数据竞争,使得多线程代码可以安全地共享数据,而不需要繁琐的锁。
  • 零成本抽象:高级语言特性(如泛型、迭代器、闭包)在编译后生成的机器码与手写底层代码性能相当。
  • 实用主义:提供包管理器 Cargo、内置测试框架、文档生成工具,让工程化体验接近现代高级语言。

为什么选择 Rust? 如果你需要编写操作系统内核、嵌入式固件、游戏引擎、数据库引擎、WebAssembly 模块或高性能网络服务,Rust 能让你在享受现代语言表达能力的同时,获得与 C/C++ 相当的性能。它的学习曲线较陡,但一旦掌握所有权模型,代码的健壮性会显著提升。

1.2 安装 Rust 工具链

Rust 官方推荐的安装方式是使用 rustup,它是一个版本管理器和工具链安装器。rustup 允许你安装多个 Rust 版本(stable、beta、nightly)并在它们之间切换,同时管理交叉编译目标。

安装步骤(Linux/macOS):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

安装完成后,需要将 Cargo 的 bin 目录添加到 PATH 环境变量。rustup 会自动在 ~/.cargo/env 中写入配置,你只需执行:

source ~/.cargo/env

Windows 用户:请前往 rustup.rs 下载 rustup-init.exe,运行后按提示操作。Windows 上 Rust 需要 MSVC 构建工具(Visual Studio Build Tools)或 GNU 工具链,建议选择 MSVC 版本。

安装完成后,验证工具链是否正常:

rustc --version
cargo --version
rustup --version

你应该看到类似如下的输出:

rustc 1.78.0 (9b00956e5 2024-04-29)
cargo 1.78.0 (54d8815d0 2024-04-29)
rustup 1.27.1 (54dd3d00f 2024-04-24)
工具 作用 常用命令
rustup 管理 Rust 工具链版本 rustup update / rustup default stable
rustc Rust 编译器 rustc main.rs
cargo 包管理器与构建系统 cargo new / cargo build / cargo run
rustfmt 代码格式化工具 cargo fmt
clippy 静态代码检查工具 cargo clippy

经验提醒:如果你在安装过程中遇到网络问题,可以设置镜像源。中国用户可以使用字节跳动的镜像:export RUSTUP_DIST_SERVER=https://rsproxy.cn 和 export RUSTUP_UPDATE_ROOT=https://rsproxy.cn/rustup。

1.3 使用 Cargo 创建第一个项目

Cargo 是 Rust 的官方构建系统和包管理器,类似于 Python 的 pip + setuptools、Node.js 的 npm。它负责依赖管理、编译、测试、文档生成和发布。Cargo 的核心理念是“约定优于配置”——项目结构有标准模板,无需手动编写构建脚本。

创建新项目的标准流程:

  1. 打开终端,进入你希望存放项目的目录。
  2. 执行 cargo new hello_world,Cargo 会自动生成一个名为 hello_world 的目录。
  3. 进入项目目录:cd hello_world。
  4. 查看生成的文件结构。
  5. 编辑 src/main.rs 写入代码。
  6. 执行 cargo run 编译并运行。

执行 cargo new hello_world 后,Cargo 会生成以下结构:

hello_world/
├── Cargo.toml   # 项目清单文件(类似 package.json)
├── .gitignore   # Git 忽略规则
└── src/
    └── main.rs  # 主程序入口

Cargo.toml 是项目的核心配置文件,默认内容如下:

[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]

其中 edition 字段指定了 Rust 的版本版本(2015、2018、2021、2024),它影响语言特性的可用性。目前推荐使用 2021 或 2024 edition。

src/main.rs 的默认内容为:

fn main() {
    println!("Hello, world!");
}

这是 Rust 程序的最小完整结构:fn main() 是程序的入口点,所有可执行程序都必须包含一个 main 函数。println! 是一个宏(注意末尾的感叹号),用于向标准输出打印一行文本并换行。

1.4 理解 main 函数与 println! 宏

main 函数是 Rust 可执行程序的唯一入口。它的签名固定为 fn main(),不接受参数,不返回任何值(实际上可以返回 Result 类型,但默认返回单元类型 ())。当程序启动时,操作系统调用 main 函数;当 main 函数执行完毕,程序退出。

println! 宏是 Rust 中最常用的输出宏。它支持格式化字符串,语法与 Python 的 f-string 和 C 的 printf 类似,但更安全——编译器会在编译期检查格式字符串与参数是否匹配。

基本用法示例:

fn main() {
    let name = "Alice";
    let age = 30;
    
    // 最简单的用法:打印字符串字面量
    println!("Hello, world!");
    
    // 使用占位符 {} 打印变量
    println!("My name is {} and I am {} years old.", name, age);
    
    // 使用位置参数
    println!("{0} is {1} years old. {0} loves Rust.", name, age);
    
    // 使用命名参数
    println!("{name} is {age} years old.", name = "Bob", age = 25);
    
    // 调试输出(用于打印结构体等复杂类型)
    println!("{:?}", vec![1, 2, 3]);
}

注意 println! 的 ! 表示这是一个宏调用,而不是普通函数。宏在编译期展开,可以接受可变数量的参数,并且能对格式字符串进行静态检查。这是 Rust 宏系统的一个典型应用。

常见误区:初学者经常忘记 println! 末尾的感叹号,写成 println("...")。这会导致编译错误,因为 println 并不是一个已定义的函数。Rust 的宏调用必须使用感叹号。另外,println! 会自动在末尾添加换行符,如果你不想换行,应使用 print! 宏。

1.5 实战场景:编译并运行你的第一个程序

现在让我们完整地走一遍从创建到运行的流程,并观察每一步的输出。

步骤 1:创建项目

$ cargo new hello_world
     Created binary (application) `hello_world` package

步骤 2:修改 main.rs

使用你喜欢的编辑器打开 src/main.rs,将内容替换为:

fn main() {
    let project_name = "Rust 入门";
    let days = 45;
    println!("欢迎来到{}课程!", project_name);
    println!("我们将在 {} 天内精通 Rust。", days);
    println!("今天是第 1 天,加油!");
}

步骤 3:编译并运行

$ cargo run
   Compiling hello_world v0.1.0 (/path/to/hello_world)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
     Running `target/debug/hello_world`
欢迎来到Rust入门课程!
我们将在 45 天内精通 Rust。
今天是第 1 天,加油!

观察输出,你会发现 Cargo 先编译了项目,然后自动运行生成的可执行文件。编译产物位于 target/debug/ 目录下。如果你只想编译不运行,可以使用 cargo build;如果想发布优化版本,使用 cargo build --release。

步骤 4:检查代码质量

Rust 生态提供了两个必备的代码质量工具:

$ cargo fmt   # 自动格式化代码
$ cargo clippy # 静态检查,发现潜在问题

如果代码风格有问题,cargo fmt 会自动修正;cargo clippy 会给出改进建议。建议每次写完代码都运行这两个命令。

1.6 常见误区与总结复盘

在 Rust 入门阶段,初学者最容易遇到以下几个问题:

误区 现象 正确做法
忘记宏的感叹号 编译错误:cannot find function `println` println! 和 print! 必须带 !
字符串拼接使用 + 编译错误:cannot add &str to &str 使用 format! 宏或 push_str 方法
忽略 Cargo.toml 依赖管理混乱 所有依赖必须在 [dependencies] 中声明
直接运行 rustc 无法管理依赖 使用 cargo 作为统一入口
不运行 cargo fmt 代码风格不统一 养成每次提交前运行 fmt 的习惯

本章复盘:

  • Rust 的核心优势是内存安全与高性能的完美结合,适合系统级开发。
  • rustup 是安装和管理 Rust 工具链的标准方式,务必确保 PATH 配置正确。
  • Cargo 是 Rust 的构建系统和包管理器,cargo new 创建项目,cargo run 编译并运行。
  • main 函数是程序入口,println! 是输出宏,支持格式化字符串。
  • 项目结构遵循约定:Cargo.toml 描述项目,src/main.rs 存放源码。

学习建议:本章内容虽然基础,但请务必亲手敲一遍所有命令。Rust 是一门实践性极强的语言,只看不练很难真正理解所有权和借用等核心概念。建议在接下来的 44 天里,每天至少写 30 行 Rust 代码,保持手感。