本文 AI 產出,尚未審核

Rust 測試與文件

單元:文件註解(/////!


簡介

在 Rust 生態系統中,文件註解是產生高品質 API 文件的核心工具。透過 ///(行內文件註解)與 //!(模組層級文件註解),開發者可以直接在程式碼中撰寫說明、範例、甚至測試,讓 cargo doc 自動產出完整、易讀的 HTML 文件。良好的文件不只提升程式碼可讀性,也讓團隊協作更順暢,對外部使用者而言,更是降低學習門檻的關鍵。

本篇文章將從 概念實作範例常見陷阱最佳實踐,到 實務應用,一步步帶你掌握 Rust 的文件註解寫法,讓你的程式庫在 Rust 官方文件 中光彩照人。


核心概念

1. /// – 行內文件註解

/// 放在 項目(function、struct、enum、trait…)的前一行,會被 rustdoc 解析為該項目的說明文字。它支援 Markdown 語法,且可以加入 程式碼範例,這些範例會在 cargo test 時自動執行(稱為 doctest)。

範例 1:簡單的函式說明

/// 計算兩個整數的和。
///
/// # 範例
/// ```
/// let sum = add(2, 3);
/// assert_eq!(sum, 5);
/// ```
///
/// 這個函式接受兩個 `i32`,回傳它們的相加結果。
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

重點

  • /// 必須緊貼在項目前,且每行都以 /// 開頭。
  • # 範例(或 # Examples)是慣用的標題,方便 rustdoc 產生目錄。
  • 程式碼區塊使用三個反引號 ```,並在開頭標註語言 rust,讓語法高亮正確。

2. //! – 模組層級文件註解

//! 用於 檔案或模組的最前面,說明整個模組的目的、使用方式或設計哲學。它同樣支援 Markdown,且常與 modcrate 的根檔案(lib.rsmain.rs)結合,提供套件的總體說明。

範例 2:crate 根文件的說明

//! # my_crate
//!
//! `my_crate` 提供簡易的數學運算工具,包含加、減、乘、除等函式。
//!
//! ## 使用方式
//! ```rust
//! use my_crate::math::{add, sub};
//!
//! let a = add(10, 5);
//! let b = sub(10, 5);
//! assert_eq!(a, 15);
//! assert_eq!(b, 5);
//! ```
//!
//! 更多細節請參考各模組的文件。

提示//! 常放在檔案最上方,不要與程式碼混在同一行,否則會被視為普通註解而不會出現在文件中。


3. Markdown 與 rustdoc 的結合

rustdoc 會把文件註解中的 Markdown 直接轉成 HTML。以下是常用的 Markdown 標記:

Markdown 產生的效果
# 標題 <h1>
## 標題 <h2>
`code` 行內程式碼
rust<br>...<br> 程式碼區塊,支援語法高亮
> 引言 引用區塊
- 列表 無序清單
1. 列表 有序清單
**粗體***斜體* 文字強調

4. Doctest – 文件中的測試

只要在文件註解裡寫上可編譯的程式碼區塊,cargo test 會自動把它當作測試執行。這讓文件與測試同步,文件永遠不會過時

範例 3:失敗的 Doctest

/// 取得字串的長度。
///
/// # 範例
/// ```
/// let len = str_len("hello");
/// // 這裡故意寫錯,測試會失敗,提醒開發者文件與實作不符。
/// assert_eq!(len, 10);
/// ```
pub fn str_len(s: &str) -> usize {
    s.len()
}

執行 cargo test 時會得到:

---- str_len::str_len (line 4) stdout ----
thread 'str_len::str_len (line 4)' panicked at 'assertion failed: `(left == right)`
  left: `5`,
 right: `10`', src/lib.rs:9:5

教訓:Doctest 能即時捕捉文件與程式碼的偏差,務必保持範例正確。


5. 文件註解的可見範圍

註解類型 作用範圍 常見使用位置
/// 針對緊鄰的項目(function、struct、enum、trait) 函式、結構體、列舉等
//! 整個檔案或模組(module) lib.rsmain.rs、子模組檔案

常見陷阱與最佳實踐

1. 註解位置錯誤

  • 陷阱:把 /// 寫在項目之後,或在 //! 前插入其他程式碼,會導致 rustdoc 無法辨識。
  • 最佳實踐始終/// 放在項目 前一行//! 放在檔案 最上方

2. Doctest 沒有 rust 標籤

  • 陷阱:使用 ``` 而未指定語言,rustdoc 仍會執行測試,但語法高亮會失效。
  • 最佳實踐:在程式碼區塊開頭寫上 rust,確保高亮與測試正確。

3. 文件過於冗長或缺乏範例

  • 陷阱:只寫一兩句說明,或把所有細節塞在同一段落,讀者難以快速掌握。
  • 最佳實踐分段說明:概述 → 參數說明 → 回傳值 → 範例 → 錯誤處理。使用 Markdown 標題 (##, ###) 讓文件結構清晰。

4. 使用 pub(crate)pub(super) 時忘記文件

  • 陷阱:私有或僅在 crate 內可見的項目若缺少文件,cargo doc --open 仍會顯示「未註解」警告。
  • 最佳實踐:即使是私有項目,也建議加上簡短說明,尤其是公共 API 的實作細節。

5. 文件與程式碼脫節

  • 陷阱:隨著功能變更,忘記同步更新文件,導致使用者閱讀過時資訊。
  • 最佳實踐:將 文件更新 列入 Pull Request 的必備檢查項目,或使用 CI 工具(如 cargo test --doc)確保 Doctest 通過。

實際應用場景

1. 開源套件的 API 文件

在 crates.io 上發布套件時,完整且正確的文件是吸引用戶的第一關卡。使用 /// 為每個公開函式、結構體提供說明與範例,讓使用者在 cargo doc --open 時即可看到即時可執行的範例。

2. 內部企業庫的自動化文件

企業內部的共用庫往往缺乏正式文件,導致新加入的開發者必須閱讀原始碼才能了解使用方式。透過 //! 為模組寫上概覽說明,配合 /// 的細部說明與 Doctest,可自動產出 內部維基HTML 手冊,減少知識傳遞成本。

3. 教學範例與測試的雙重角色

在教學文章或部落格中,常會直接貼上 /// 範例。讀者可以把這段程式碼貼回自己的專案,或直接在 Playground 上執行。因為 Doctest 已經驗證過,範例不會因為版本升級而失效

4. 產生自訂文件(如 PDF、Markdown)

rustdoc 支援 --output-format json,開發者可以把產出的 JSON 轉換成其他格式(如 PDF、GitBook)。只要文件寫得完整,轉換過程就不會遺失資訊。


總結

  • /// 用於 項目層級 的說明,支援 Markdown 與 Doctest,讓 API 文件與測試同步。
  • //! 用於 模組或檔案層級 的概覽,提供整體說明與使用指南。
  • 正確的 位置語言標籤範例,是產出高品質文件的關鍵。
  • Doctest 不僅是測試工具,也是防止文件過時的最佳防線。
  • 在開源、企業內部或教學情境中,善用文件註解可以大幅提升可讀性、可維護性與使用者體驗。

掌握了這兩種註解的寫法與最佳實踐,你的 Rust 專案將不再是「黑盒」程式碼,而是 自說自明、即插即用 的高品質函式庫。現在就把這些技巧應用到你的下一個 crate,讓文件成為你的最佳代碼夥伴吧!