手把手带你写 Rust 文档
在 Rust 中,文档不是代码的“附属品”,而是程序开发的一部分。Rust 为文档提供了原生的工具链支持,达到文档即代码、文档即测试的效果,这也是为什么 Rust 生态的库普遍有极高的文档质量。这篇文章会手把手带你写 Rust 文档,从基础语法、高级技巧,到最佳实践,写出符合 Rust 社区规范、可维护、高可用性的技术文档。
rustdoc 入门
Rust 文档的核心工具是 rustdoc,它是 Rust 官方内置的文档生成器,和 Cargo 深度集成,可以通过下面的命令使用:
rustdoc --version# cargo doc 是调度 rustdoc 的便捷封装cargo doc --version
命令速查
在项目根目录执行以下命令,就能完成文档的生成、预览和测试:
|
|
|
|---|---|
cargo doc |
|
cargo doc --open |
|
cargo doc --no-deps |
|
cargo test --doc |
|
cargo doc --offline |
|
文档注释语法
Rust 严格区分了普通注释和文档注释:普通注释是给代码维护者看的,不会被 rustdoc 解析,而文档注释是给用户看的,会被渲染到文档页面中。
四种注释的区别与用法
|
|
|
|
|
|---|---|---|---|
// 内容 |
|
|
|
/* 内容 */ |
|
|
|
/// 内容 |
|
|
|
/** 内容 */ |
|
|
/// 一致 |
//! 内容 |
|
|
|
第一行文档注释
我们先给一个简单的加法函数写文档,如下所示:
/// 计算两个整数的和,返回相加后的结果////// 这是一个基础的整数加法函数,支持正负数、零的运算,/// 不会做溢出检查,溢出行为遵循 Rust 整数溢出规则pub fn add(a: i32, b: i32) -> i32 { a + b}
执行 cargo doc --open,你就能在文档中看到这个函数的完整说明,rustdoc 会自动把注释内容渲染到函数的详情页中。

Markdown 的支持
rustdoc 对 Markdown 的支持还是比较全面的,包括代码块(带语法高亮)、列表、链接、表格等标准的 Markdown 语法。
基础 Markdown 语法
你可以在文档注释中使用所有常用的 Markdown 语法:
-
• 标题: # 一级标题、## 二级标题,推荐二级及以下标题用于文档内部分段 -
• 列表:有序列表 1. xxx、无序列表- xxx -
• 代码块:用于写可运行的示例 -
• 强调: **加粗**、*斜体* -
• 链接: [链接文本](链接地址) -
• 表格:常用于参数对比、特性说明等 -
• 引用块: > 内容,常用于提示、警告信息
文档内链接(Intra-doc Links)
这是 Rust 文档的特性之一:你可以在文档中直接链接到当前 crate、标准库、其他 crate 的任意 API 项,用户点击就能跳转到对应页面。
语法比较简单,直接用[项名]即可完成链接,rustdoc 会自动解析路径并生成跳转链接:
/// 数学运算相关的错误类型枚举#[derive(Debug, PartialEq, Eq)]pub enum MathError { /// 除零错误,当除数为 0 时触发 DivideByZero, /// 整数溢出错误 Overflow,}/// 整数除法运算,返回商或错误////// # Errors/// 当除数 `b` 为 0 时,返回 [MathError::DivideByZero]pub fn divide(a: i32, b: i32) -> Result<i32, MathError> { if b == 0 { return Err(MathError::DivideByZero); } Ok(a / b)}
上面的例子中,[MathError::DivideByZero] 会自动生成跳转到该枚举项的链接,用户点击就能看到对应的定义和说明。
文档即测试
Rust 文档中最惊艳的功能之一就是文档测试(Doctest),这是其他编程语言中基本没有的功能。rustdoc 会把你文档里的 rust 代码块,当成单元测试来编译运行。这也就解决了文档和代码不同步的痛点,只要你改了代码,文档里的示例跑不通,测试就会直接报错,强制你同步更新文档。
第一个文档测试
我们给 add 函数的文档加上可运行的测试:
/// 计算两个整数的和,返回相加后的结果////// # 示例/// ```rust/// use doc_example::add;////// // 基础加法/// assert_eq!(add(2, 3), 5);/// // 正负数相加/// assert_eq!(add(-1, 1), 0);/// ```pub fn add(a: i32, b: i32) -> i32 { a + b}
执行 cargo test --doc,你会看到如下输出:
running 1 testtest src/lib.rs - add (line 22) ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
隐藏辅助代码
很多时候,示例需要一些导入、main 函数等辅助代码,但这些代码会让文档变得冗余。你可以用 # 开头的行,标记这段代码会被编译运行,但不会渲染在文档中:
/// 除法运算示例////// ```rust/// # use doc_example::{divide, MathError};/// # fn main() -> Result<(), MathError> {/// let result = divide(10, 2)?;/// assert_eq!(result, 5);/// # Ok(())/// # }/// ```
渲染后的文档只会显示核心的两行代码,隐藏的 use、main 函数会在测试时正常运行,完美解决了 Result 类型的错误处理问题。
测试属性标记
你可以在代码块的开头添加属性,控制测试的行为:
|
|
|
|---|---|
rust,should_panic |
|
rust,ignore |
|
rust,no_run |
|
rust,compile_fail |
|
示例如下:
/// 除零场景示例////// ```rust,should_panic/// use doc_example::divide;////// // 除零会触发 panic/// divide(10, 0).unwrap();/// ```
非 Rust 代码块
如果你需要展示其他格式的内容,比如 JSON、文本、Shell 命令,只需要指定对应的语言标识,rustdoc 就不会把它当成测试:
/// 配置文件格式示例////// ```toml/// [math]/// precision = 10/// enable_overflow_check = true/// ```
渲染 Mermaid 流程图
rustdoc 并不支持原生渲染 Mermaid 流程图,但是我们可以使用 aquamarine[1] 这个库来达成效果,它是 rustdoc 的过程式宏扩展。
步骤一:添加依赖
cargo add aquamarine
步骤二:使用 Mermaid 流程图
#[cfg_attr(doc, aquamarine::aquamarine)]/// 计算器运算流程////// ```mermaid/// graph LR/// A[设置初始值] --> B[加法运算]/// B --> C{是否除零?}/// C -->|否| D[除法运算]/// C -->|是| E[返回除零错误]/// D --> F[输出最终结果]/// ```pub fn example() {}
渲染后的效果如下:

文档属性
Rust 提供了一系列 #[doc] 属性,让开发者可以精细化控制文档的渲染、可见性、搜索等行为,满足复杂场景的需求。
|
|
|
|
|---|---|---|
#[doc = "内容"] |
|
#[doc = concat!("这是", "动态生成", "的文档")] |
#[doc(hidden)] |
|
|
#[doc(alias = "别名")] |
|
|
#[doc(inline)] |
|
|
#[doc(no_inline)] |
|
|
#[cfg(doc)] |
|
|
#![deny(missing_docs)] |
|
lib.rs 顶部,用于团队规范约束 |
最佳实践
Rust 社区有一套公认的文档规范,如下所示:
-
• 一句话摘要:文档的第一行必须是一句话,精准概括这个项的核心作用 -
• 详细描述:补充适用场景、设计思路、边界情况,告诉用户“什么时候用、什么时候不该用” -
• 示例优先:先给可运行的核心示例,再讲参数、返回值等细节 -
• 专项说明:按需添加 # Parameters、# Returns、# Errors、# Panics、# Safety、# Performance等专项章节 -
• 公开项必写文档:所有 pub的项都必须有文档,用#![deny(missing_docs)]强制约束 -
• 文档和代码同步:改了代码不改文档,文档测试就是为了解决这个问题,确保每个示例都能跑通 -
• unsafe 函数必须写 Safety 说明:这是 Rust 社区的硬性规范,所有 unsafe函数必须写清楚调用者需要遵守的安全约束
最后,想要写出高质量的文档,最好的方法就是学习顶级开源库的写法,比如 Rust 标准库文档[2],它应该是最权威的文档规范范本了,另外,像 serde、tokio、anyhow 等库的文档也值得拿来学习。
总结
Rust 文档的核心,从来都不是语法和工具,而是“站在用户的角度思考”,你写的每一行文档,都是为了让用户能快速理解、正确使用你的代码。
引用链接
[1] aquamarine: https://docs.rs/aquamarine/latest/aquamarine/[2] Rust 标准库文档: https://doc.rust-lang.org/std/
夜雨聆风