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 最佳實務。請在同一輪中平行閱讀所有相關章節。提供意見回饋時,請參考以下檔案:
- 第一章 - 程式碼風格與慣用寫法:借用 vs 複製、Copy trait、Option/Result 處理、迭代器、註解
- 第二章 - Clippy 與 Linting:Clippy 設定、重要 lint、工作區 lint 設定
- 第三章 - 效能思維:效能剖析、避免重複複製、堆疊 vs 堆積、零成本抽象
- 第四章 - 錯誤處理:Result vs panic、thiserror vs anyhow、錯誤層級
- 第五章 - 自動化測試:測試命名、每個測試一個斷言、快照測試
- 第六章 - 泛型與分派:靜態 vs 動態分派、trait 物件
- 第七章 - 型別狀態模式:編譯時期狀態安全、使用時機
- 第八章 - 註解 vs 文件:何時加註解、doc 註解、rustdoc
- 第九章 - 理解指標:執行緒安全、Send/Sync、指標型別
快速參考
借用與所有權
- 除非需要轉移所有權,否則優先使用
&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)]






