Rust 命令速查表 - Rust 与 Cargo 常用命令大全

这套速查给写 Rust 的开发者,尤其围绕每天都要碰的 Cargo 工具链:项目脚手架、debug 与 release 两态编译、跑测试、生成文档、用 Clippy 扫 lint、用 rustfmt 统一格式、按目标平台交叉编译。与逐个罗列 cargo 子命令不同,条目沿"编辑→编译/检查→测试→lint→格式化→发布"的真实节奏组织。读完应能把一个新 crate 从 cargo new 一路带到 green 的 Clippy+测试和可交付的 release 构建。

编程语言·共 51 条命令·最后更新 2026-07-21
rustcargo编程

典型使用场景

面向用 Rust 写服务、CLI 或并发 worker 的开发者。Rust 的学习曲线主要卡在所有权与借用检查,本表把两块分开处理:一块是 cargo 命令行(项目管理、依赖、测试、检查、发布、交叉编译),另一块是语法核心(所有权、借用、生命周期省略、Result 与 ? 传播)。高频写代码时用 cargo check 做快速类型验证比 cargo build 快得多,这是最值得先改掉的一个习惯。

项目管理 9

cargo new project_name
创建可执行(二进制)新项目并初始化 git 仓库,默认使用你的 git 配置
cargo new --lib project_name
创建库(lib)型项目,入口是 src/lib.rs 而非 main.rs,适合封装可复用 crate
cargo init
在当前目录初始化 Cargo 项目,适合已有源码目录补脚手架
cargo build
编译为 debug 版本(产物在 target/debug),不经优化、编译快,符合日常开发
cargo build --release
以 release 优化编译(target/release),产物更小运行更快,上线用这个构建
cargo run
编译并直接运行二进制,省略先 build 再手动执行,开发快捷键
cargo run --release
编译并运行发布版本,用于验证优化后的实际性能
cargo check
只做类型检查不生成二进制,最快验证代码能否通过借位检查与类型系统,适合频繁改动时用
cargo clean
清空 target 目录全部构建缓存,解决陈旧的增量编译问题时再重编

依赖管理 6

cargo add serde
把最新兼容版本的 serde 写入 Cargo.toml 并可直接 use,无需手工编辑清单
cargo add serde --features derive
添加依赖并同时开启其 derive feature,便于后续派生宏(如 #[derive(Serialize)])
cargo remove serde
从 Cargo.toml 移除依赖声明,同时清理不再需要的引用
cargo update
按 Cargo.toml 约束把 Cargo.lock 中的依赖升级到当前满足的最新版本
cargo tree
以树形打印依赖关系,直观看到传递依赖与版本来源
cargo tree --invert
反向查询到底哪些 crate 依赖着某个具体包,查连锁升级影响面用它

测试与文档 5

cargo test
运行所有测试
cargo test -- --nocapture
显示 println 输出
cargo test test_name
运行指定测试
cargo doc --open
生成并打开文档
cargo doc --no-deps
仅生成当前 crate 文档

代码质量 4

cargo clippy
运行 Clippy lint 检查
cargo clippy --fix
自动修复 Clippy 警告
cargo fmt
格式化代码
cargo fmt -- --check
检查格式(CI 用)

发布与跨平台 6

cargo publish
发布到 crates.io
cargo publish --dry-run
模拟发布
cargo build --target x86_64-unknown-linux-musl
交叉编译到 Linux
rustup target list
列出可用目标平台
rustup target add x86_64-pc-windows-gnu
添加 Windows 目标
cargo install cargo-edit
安装全局命令

语法核心 14

let s2 = s1;
所有权转移(move 语义)
let r = &s;
不可变引用(借用)
let r = &mut s;
可变引用
fn foo<'a>(x: &'a str) -> &'a str
显式生命周期标注
fn foo(x: &str) -> &str
生命周期省略规则
match x { Some(v) => v, None => 0 }
match 模式匹配
if let Some(v) = opt {}
if let 简化匹配
while let Some(v) = iter.next() {}
while let 循环匹配
let Ok(v) = res else { return; };
let-else 语法(不匹配则返回)
Result<T, E>
结果类型(成功或错误)
Option<T>
可空类型(Some/None)
fn foo() -> Result<T, E>
返回 Result 便于错误传播
result?
错误传播运算符(出错则提前返回)
#[derive(Debug, Clone, PartialEq)]
自动派生 trait 实现

模块系统 7

use std::collections::HashMap;
导入模块
use std::io::{self, Read};
导入多个项(含重命名 self)
mod my_module;
声明子模块(从文件加载)
pub fn foo() {}
公开可见性
pub(crate) fn internal()
仅 crate 内可见
pub use crate::utils::helper;
重导出(re-export)
crate::module::func()
绝对路径引用

参数矩阵

参数作用示例
cargo new --lib创建库型项目,入口 src/lib.rscargo new --lib mylib
cargo check只做类型检查不生成二进制,最快cargo check
cargo build --release优化构建,产物在 target/releasecargo build --release
cargo add serde --features derive加依赖并开启 featurecargo add serde --features derive
cargo update按约束升级 lock 中的依赖cargo update
cargo tree --invert反查哪些 crate 依赖了某包cargo tree --invert serde
cargo clippy --fix运行 lint 并自动修复cargo clippy --fix
cargo fmt -- --check格式检查,CI 门禁用cargo fmt -- --check
result?错误传播:出错即提前返回let v = parse(s)?;
&s / &mut s不可变 / 可变借用fn f(s: &mut String)
#[derive(Debug, Clone)]自动派生 trait 实现#[derive(Debug, Clone, PartialEq)]
rustup target add <triple>为交叉编译添加目标平台rustup target add x86_64-pc-windows-gnu

易错点与避坑指南

现象编译报 cannot move out of ... ,值在使用后又被引用。

原因赋值/传参默认是所有权转移(move),原变量失效。

处置改用借用 &s 传参;确需持有两份时用 s.clone()。

现象同一作用域内同时可变借用了两次,编译器报 borrow conflict。

原因Rust 在任意时刻只允许一个 &mut 借用。

处置把两次借用拆到不同作用域,或改用索引/拆分数据结构避免重叠生命周期。

现象函数返回引用时报 missing lifetime specifier。

原因返回值引用了参数时,编译器无法推断生命周期关系。

处置显式标注 fn foo<'a>(x: &'a str) -> &'a str,或让函数直接接收并返回 String 避免引用。

现象cargo build 突然变慢或报奇怪的编译错误,重编后又好了。

原因target 目录里的增量编译缓存与当前源码状态不一致。

处置cargo clean 清空 target 后重编。

现象升级依赖后编译失败,锁文件已自动被改动。

原因cargo update 把 Cargo.lock 里的次要依赖一并升级。

处置升级前备份 lock;用 cargo update -p <crate> --precise <ver> 精确控制单个依赖版本。

现象交叉编译报错,缺少链接器或找不到 target。

原因未安装对应平台目标,或缺少该平台的链接工具链。

处置rustup target add <triple> 安装目标,并确认所需的交叉链接器已就位。

排障路径

  1. 1先用最快的检查确认能否编译

    cargo check

    不生成二进制,最快验证类型与借用检查;日常改代码首选。

  2. 2定位是谁引入了某个依赖

    cargo tree --invert serde

    反向查询连锁升级的影响面,决定能否移除。

  3. 3缓存出问题时的彻底重建

    cargo clean && cargo build

    清空 target 目录;只在怀疑缓存不一致时用,会全量重编。

  4. 4发布前先模拟一次

    cargo publish --dry-run

    不真正发布,验证打包与元数据是否符合 crates.io 要求。

  5. 5CI 里的质量门禁

    cargo fmt -- --check && cargo clippy

    格式与 lint 都过再构建,是最小可用的 CI 检查组合。

命令示例

加依赖并顺手开 feature,不要手改 Cargo.toml

cargo add serde --features derive

derive feature 决定能否写 #[derive(Serialize)]。用 cargo add 还会自动选一个与你当前工具链兼容的版本号并写进 Cargo.toml,手改清单则容易留下一个解析不了的版本约束。

输出

    Adding serde v1.0.210 to dependencies
    Adding serde_derive v1.0.210 to dependencies

升级某个包前先看它被谁依赖

cargo tree --invert serde

反向依赖树回答的是「谁依赖了我」,正向 cargo tree 回答的是「我依赖了谁」。评估一次可能引发连锁升级的改动(尤其是加 feature)时,先 --invert 看清影响面,再决定要不要动。

输出

my-app v0.1.0
└── serde v1.0.210

调试时让 println 真的打印出来

cargo test -- --nocapture

测试默认捕获 stdout,通过的测试不会打印任何东西,于是「我明明写了 println 却没看到」成为最常见的困惑。-- --nocapture 把参数透传给测试二进制,关掉捕获。中间那对 -- 是必须的:cargo 之后、交给测试运行时的参数之前。

CI 里用 fmt --check 把格式卡死

cargo fmt -- --check

不加 -- --check 时 cargo fmt 会直接改写文件;加了它就变成只检查、有差异就非零退出。CI 里用 check 版本,提交前本地跑 cargo fmt 真正落盘,两者配对使用。

输出

Diff in /src/main.rs at line 14:
-  let x=1;
+  let x = 1;

let-else 把「不匹配就退出」写在一行

let Ok(value) = config.get("port") else { return; };

表里的 match / if let / while let / let-else 是同一套模式的四种写法。let-else 的特点是必须 else 分支发散(return、break、panic),编译器才能把它收窄成后续可用的绑定,避免了 Option 层层解包。

常见坑与注意事项

  • cargo clean 会删掉整个 target 目录,一次性丢掉全部增量编译缓存,几分钟的编译重来;只在增量编译结果确实错乱时才用。
  • Cargo.lock 必须提交进版本库:库项目也应提交,否则不同机器解析出的传递依赖版本不同,问题无法复现。
  • cargo update 会在满足约束的前提下把锁文件里的版本推到最新,diff 可能很大;上线前后的依赖升级要单独成一次提交,出问题才好二分定位。
  • cargo publish --dry-run 只跳过真正的上传,打包、校验与依赖图检查都会真跑,但版本号一旦被占用就无法复用,发布前务必先 dry-run。
  • 交叉编译只负责产出目标平台的代码,链接阶段仍需要对应工具链(如 Linux musl 目标的 linker);缺工具链时报错发生在链接而不是编译,容易误判成源码问题。
  • cargo clippy --fix 会批量改写源码,改动常常超出预期范围;必须先看 clippy 的报告、再在干净的提交上让它改,并复核 diff。

提示

  • cargo check 比 cargo build 快很多,日常开发用它检查编译错误。
  • cargo clippy 是官方 lint 工具,建议加入 CI 流程。
  • 发布前务必运行 cargo publish --dry-run 验证。
  • 同一时间只能有一个可变引用或多个不可变引用,二者不可共存。
  • ? 运算符只能在返回 Result 的函数中使用,自动将 Err 向上传播。
  • 生命周期省略规则适用于常见模式,复杂场景需显式标注 lifetime 参数。

常见问题

cargo check 和 cargo build 什么时候用哪个?

日常改代码时用 cargo check——它只做类型与借用检查,不生成二进制,比 cargo build 快很多,适合频繁小步改动。确认没问题后 cargo build 产出 debug 版本(在 target/debug,不开优化,编译快),上线前用 cargo build --release 拿到 target/release 的优化产物。想直接看运行效果用 cargo run,加 --release 可以验证优化后的真实性能。遇到莫名其妙的增量编译错误,最后再用 cargo clean 清空 target 重来。

报同时存在两个可变引用,怎么改?

Rust 的核心规则是同一时刻只能有一个 &mut 引用,或者任意多个 & 不可变引用,二者不能共存。典型冲突是两个作用域各自持有 &mut s,比如分别 &mut vec[0] 和 &mut vec[1]。解决办法是先用不可变借用把需要的值取出来、结束借用再进入可变借用;或者拆分借用,对不同字段用不同变量访问;实在不行就 let s2 = s1; 直接走所有权转移,把值交出去。

什么时候该返回 Result,什么时候用 Option?

判断标准是「缺失」还是「失败」。Option<T> 表达可空,用 Some/None 包装,出现在「可能没有值」的场景,比如字典查找。Result<T, E> 表达成功或某种错误,适合返回 fn foo() -> Result<T, E>,调用方用 result? 运算符把 Err 提前向上传播——注意 ? 只能用在返回 Result 的函数里,它会把错误自动转换并 return。想简化一次性匹配用 if let Some(v) = opt {} 或 let Ok(v) = res else { return; };。

加依赖时 cargo add 和手改 Cargo.toml 有什么区别?

cargo add serde 会自动选取最新兼容版本写入 Cargo.toml 并让代码里立刻能 use,省去手工查版本号。带功能时用 cargo add serde --features derive,顺便打开派生宏支持,配合 #[derive(Debug, Clone, PartialEq)] 这类实现。删除用 cargo remove serde,它同时清理不再需要的引用清单。想在现有约束内升级已有依赖用 cargo update,它会更新 Cargo.lock 里的版本而不改清单。

升级一个依赖前,怎么先摸清它会影响到谁?

先看正向依赖树:cargo tree 以树形打印所有依赖关系,能直观看到传递依赖和版本来源。要评估某个具体包的升级影响面,用反向查询 cargo tree --invert,它列出到底哪些 crate 依赖着目标包——如果影响面比预期大,就该先降级发布再升级。下游如果担心 API 破坏影响代码,升级后依次跑 cargo check、cargo clippy、cargo fmt -- --check 和 cargo test 确认没退化。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们