rust-best-practices

rust-best-practices

根據 Apollo GraphQL 的最佳實務手冊,撰寫符合 Rust 慣用寫法的程式碼。適用於以下情況:(1) 撰寫新的 Rust 程式碼或函式;(2) 審查或重構現有 Rust 程式碼;(3) 決定借用 vs 複製或所有權模式;(4) 使用 Result 型別實作錯誤處理;(5) 最佳化 Rust 程式碼效能;(6) 為 Rust 專案撰寫測試或文件。

90星標
10分支
更新於 2026/6/4
SKILL.md
唯讀
名稱
rust-best-practices
描述

根據 Apollo GraphQL 的最佳實務手冊,撰寫符合 Rust 慣用寫法的程式碼。適用於以下情況:(1) 撰寫新的 Rust 程式碼或函式;(2) 審查或重構現有 Rust 程式碼;(3) 決定借用 vs 複製或所有權模式;(4) 使用 Result 型別實作錯誤處理;(5) 最佳化 Rust 程式碼效能;(6) 為 Rust 專案撰寫測試或文件。

Rust 最佳實務

撰寫或審查 Rust 程式碼時,請遵循以下準則。本指南基於 Apollo GraphQL 的 Rust 最佳實務手冊

最佳實務參考

在審查之前,請先熟悉 Apollo 的 Rust 最佳實務。請在同一輪中平行閱讀所有相關章節。提供意見回饋時,請參考以下檔案:

快速參考

借用與所有權

  • 除非需要轉移所有權,否則優先使用 &T 而非 .clone()
  • 函式參數優先使用 &str 而非 String&[T] 而非 Vec<T>
  • 小型 Copy 型別(≤24 位元組)可以傳值
  • 當所有權不明確時,使用 Cow<'_, T>

錯誤處理

  • 可能失敗的操作回傳 Result<T, E>;避免在正式環境中使用 panic!
  • 絕不在測試以外的程式碼中使用 unwrap()/expect()
  • 函式庫錯誤使用 thiserror,僅二進位檔使用 anyhow
  • 錯誤傳播優先使用 ? 運算子而非 match 鏈

效能

  • 務必使用 --release 旗標進行基準測試
  • 執行 cargo clippy -- -D clippy::perf 取得效能提示
  • 避免在迴圈中複製;對 Copy 型別使用 .iter() 而非 .into_iter()
  • 優先使用迭代器而非手動迴圈;避免中間的 .collect() 呼叫

Linting

定期執行:cargo clippy --all-targets --all-features --locked -- -D warnings

需注意的重要 lint:

  • redundant_clone - 不必要的複製
  • large_enum_variant - 過大的變體(考慮使用 Box)
  • needless_collect - 過早的集合轉換

使用 #[expect(clippy::lint)] 而非 #[allow(...)],並附上理由註解。

測試

  • 測試命名要具描述性:process_should_return_error_when_input_empty()
  • 盡可能每個測試只有一個斷言
  • 公開 API 範例使用 doc 測試(///
  • 考慮使用 cargo insta 對產生的輸出進行快照測試

泛型與分派

  • 效能關鍵的程式碼優先使用泛型(靜態分派)
  • 僅在需要異質集合時使用 dyn Trait
  • 在 API 邊界使用 Box,而非內部

型別狀態模式

將有效狀態編碼在型別系統中,以便在編譯時期捕捉無效操作:

struct Connection<State> { /* ... */ _state: PhantomData<State> }
struct Disconnected;
struct Connected;

impl Connection<Connected> {
    fn send(&self, data: &[u8]) { /* 只有已連線才能傳送 */ }
}

文件

  • // 註解說明 為什麼(安全性、變通方法、設計理由)
  • /// doc 註解說明公開 API 的 什麼如何
  • 每個 TODO 都需要連結到一個 issue:// TODO(#42): ...
  • 函式庫啟用 #![deny(missing_docs)]