注释与文档注释
本教程共 78 篇 · 第 15 篇 · 更新于 2026-08-08 · 约 6 分钟阅读
本节目标:学会用行注释、块注释给代码加说明,并掌握文档注释
///和//!的写法,知道怎么用cargo doc一键生成网页版 API 文档。
写代码不只是给机器看,也是给人看——包括未来的你自己。注释就是写给人的说明文字,编译器会完全忽略它们。Rust 的注释分三类:行注释、块注释、文档注释。最后一种特别重要,因为它能自动变成官方文档。
15-1 行注释
两个斜杠 // 开头,到行尾结束:
fn main() {
let price = 100; // 单价,单位:元
// 下面计算总价
let total = price * 3;
}
// 后面的内容都是注释。行注释最常用,随手解释某行在干嘛。
15-2 块注释
用 /* 和 */ 包住,能跨多行:
/*
这个函数负责计算折扣价。
暂时还没实现,先占个位置。
*/
fn discount() {}
块注释适合临时屏蔽一大段代码,或写较长的多行说明。注意它不支持像某些语言那样的嵌套(/* 外层 /* 内层 */ 这样会出问题 */),实际用得不如行注释多。
Note调试时想把某段代码暂时”关掉”看效果,常用块注释把它包起来。但更规范的做法是用版本控制(git)管理,别留一堆被注释掉的死代码——别人看了会困惑”这段到底要不要?“。
15-3 文档注释 ///
前两种是给读源码的人看的。文档注释 /// 是给用你代码的人看的——它们会被 cargo doc 提取,生成漂亮的 HTML 文档,和官网标准库文档一个风格。
/// 计算两个数的和。
///
/// # 示例
/// ```
/// let r = add(2, 3);
/// assert_eq!(r, 5);
/// ```
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
/// 写在被注释的项(函数、struct 等)上方。文档里支持 Markdown,你可以写标题、列表、代码块。那个代码块还能被 cargo test 当测试跑(叫 doctest),保证文档示例不会过期。
Tip库(给别人用的 crate)的公开函数,强烈建议都写
///文档注释。你自己写的小练习用不上,但养成”重要的公开接口写文档”的习惯,受益终身。
15-4 模块级文档 //!
包在 //!(双斜杠加叹号)是写给”当前文件/模块”本身的文档,通常放在文件最顶部:
//! 这是计算价格的工具模块。
//! 提供折扣、税费等函数。
pub fn add(...) {}
/// 说的是”下面这个东西是干嘛的”,//! 说的是”这个文件/模块整体是干嘛的”。一个对外(item)、一个对内(module),别搞混。
15-5 用 cargo doc 生成文档
写好文档注释后,一条命令生成网页:
cargo doc --open
--open 会自动在浏览器打开。生成的文档在 target/doc/ 目录。发布库之前跑一下,检查文档排版对不对,是很专业的习惯。
Warning
cargo doc默认只给”公开(pub)“的项生成文档。你写在私有函数上的///不会出现在对外文档里。想给内部也生成,加--document-private-items参数。
15-6 写注释的分寸
注释不是越多越好。糟糕的注释反而添乱:
- 别写废话:
let x = 5; // 把 5 赋给 x—— 这纯属翻译代码,毫无信息量。 - 解释”为什么”,而非”是什么”:代码本身能看出”做了什么”,注释该补上”为什么这么做”(比如”这里用 u8 是因为协议规定单字节”)。
- 别让注释和代码脱节:改了代码忘了改注释,比没注释更害人。所以注释尽量写”不易过时的设计意图”。
NoteRust 社区有个理念:好的代码尽量自解释(靠清晰的命名、小的函数),注释只补”代码表达不出的背景”。与其狂写注释,不如把函数名起得让人一看就懂。
15-7 文档里的代码示例会被当测试
文档注释里写的代码块不是摆设——cargo test 会把它当成真正的测试跑起来,这叫 doctest(文档测试)。好处是:你文档里的示例永远和代码同步,一旦函数改了、示例编不过,测试立刻红。这逼着你好好维护示例,读者抄去也能跑。
/// 计算两数之和。
///
/// # 示例
/// ```
/// let r = add(2, 3);
/// assert_eq!(r, 5);
/// ```
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
上面 /// 里的三行代码,执行 cargo test 时会被编译并运行,assert_eq! 断言结果等于 5。如果哪天 add 改成返回 x * y,这个 doctest 会失败,提醒你”文档示例过期了”。
Warningdoctest 默认在独立环境编译,不能引用你
main里的私有变量。示例里用到的类型都要写成”外人能拿到”的形式(公开函数、或标准库类型)。写示例时用let r = ...配合assert_eq!是最稳妥的写法。
15-8 注释的排版与约定
写注释有些约定能让团队读着舒服。临时标记用 // TODO: 以后做、// FIXME: 这里有 bug,很多编辑器会把这些词高亮、还能汇总成任务清单。注释统一放在被说明代码的上方(或同行右侧),别写在离代码很远的地方,否则容易被忽略。
// FIXME: 边界情况未处理,大数会溢出
let total = a + b;
Warning别提交”被注释掉的死代码”到仓库——别人不知道这段代码还要不要,改了相关逻辑也不敢删它,越积越乱。确定不要的代码直接删,版本控制(git)能帮你找回历史。注释只写”说明”,不用来”存代码”。
Tip如果一段逻辑确实复杂、必须分步讲解,可以用编号注释
// 1. 校验输入 // 2. 计算 // 3. 返回串起流程,比一大段散文清晰。但最好的注释是让代码自己表达——先把函数名、变量名起好。
15-9 文档的段落标记约定
文档注释里常用几个段落标记,读者一眼能找到重点:# 示例 放可运行代码、# 参数 列参数含义、# 返回值 说返回什么、# Panics 注明什么情况会崩溃、# 错误 说可能返回的错误。这些标记不是语法强制,但是社区约定,生成文档时会渲染成小标题。
/// # Panics
/// 当除数为 0 时本函数会 panic。
Warning写
# Panics/# 错误这类”负面说明”很重要,它们告诉调用方”别这么用,会出事”。很多 bug 源于调用方不知道某个函数在某些输入下会崩。诚实写明边界条件,是对使用你代码的人负责。
15-10 注释的常见误区
注释虽简单,也有坑。一是”注释说谎”:代码改了、注释没改,留下和代码矛盾的说明,比没注释更害人——维护注释和代码一致是基本功。二是”复述代码”:写 x = x + 1; // 把 x 加一,这种注释毫无信息量,读者看代码就懂,纯属噪音。好注释讲”为什么”:为什么这里用了一个看似奇怪的偏移、为什么这个边界要特判、为什么选了这个算法。三是把机密或吐槽写进注释——代码仓库可能被多人看到,注释里别留敏感信息。
Tip一条实用标准:当你三个月后回看这段代码、会问”当时为啥这么写”时,那个答案就该写进注释。注释是给”未来的自己”和”下一个接手的人”留的线索,不是给编译器看的。
15-11 文档注释的常见误区
写文档注释时,有几个新手容易犯的错,提前点出来能少走弯路:
- 误区一:把 doctest 写成会报错的例子。文档里的代码块会被
cargo test当测试跑,所以示例必须真能编译运行。别写// 假设这里有返回值这种伪代码,它会让测试红。 - 误区二:只为”看起来专业”而写文档。私有函数、内部小工具没必要都写
///。文档是给”用你代码的人”看的,挑公开接口写,反而更清晰。 - 误区三:文档和代码脱节。函数改了逻辑,注释却没改,比没注释更坑人。养成”改代码顺手改文档”的习惯,配合 doctest 还能自动发现过期示例。
- 误区四:在
//!和///上搞混。记住一句话:///说”下面这个东西干嘛用”,//!说”这个文件/模块整体干嘛用”。前者贴在被注释项上方,后者贴在文件最顶部。
Tip一个实用的节奏:写库(给别人用的 crate)时,先把公开函数的
///文档补上,再跑一遍cargo doc --open看看渲染效果。文档质量往往是别人愿不愿意用你代码的第一印象,值得花这点工夫。
15-12 小结
// 行注释、/* */ 块注释是给读源码的人;/// 和 //! 是文档注释,喂给 cargo doc 生成 API 网页。注释贵在讲”为什么”,文档里的示例会被当测试跑(doctest)。到这,语言基础的数据类型、函数、注释都讲完了。下一章我们进入”控制流”——让程序学会判断和重复,这是写出真正有用程序的关键。