跳轉至

建立 2026-09-19 更新 2026-09-19

模組與 Crate

程式變大之後,需要把程式碼分門別類,並控制哪些部分對外公開。Rust 用「套件、crate、模組、路徑」這套系統來組織程式。本頁說明各名詞的關係,以及最常用的 modpubuse 語法。

名詞對照

名詞 說明
套件(package) 一個 Cargo 專案,由 Cargo.toml 描述,可包含一個或多個 crate
crate 編譯的最小單位,分成執行檔(binary,入口 src/main.rs)與函式庫(library,入口 src/lib.rs
模組(module) crate 內部的命名空間,用來分組與控制可見性
路徑(path) 指到某個項目的名稱,例如 crate::garden::plant

定義模組與可見性

mod 定義模組。預設所有項目都是私有的,要讓外部使用必須加上 pub

mod restaurant {
    pub mod kitchen {
        pub fn cook(dish: &str) -> String {
            format!("煮好了:{dish}")
        }

        fn secret_recipe() {} // 私有,只有 kitchen 內部能用
    }

    pub fn serve() -> String {
        // 同層的模組可以用相對路徑;super 表示上一層
        let dish = kitchen::cook("牛肉麵");
        format!("上菜!{dish}")
    }
}

fn main() {
    println!("{}", restaurant::serve());
    println!("{}", restaurant::kitchen::cook("炒飯"));
}

結構體的欄位也預設私有,需要逐一標 pub

mod shop {
    pub struct Product {
        pub name: String, // 公開
        price: u32,       // 私有:只能透過方法存取
    }

    impl Product {
        pub fn new(name: &str, price: u32) -> Product {
            Product { name: name.to_string(), price }
        }

        pub fn price(&self) -> u32 {
            self.price
        }
    }
}

fn main() {
    let p = shop::Product::new("咖啡", 120);
    println!("{} {}", p.name, p.price());
}

這是 Rust 實現「封裝」的方式:用私有欄位保護內部狀態,只透過公開方法對外提供操作。

用 use 引入路徑

每次都寫完整路徑很冗長,用 use 把名稱引入目前的作用域:

mod shapes {
    pub mod circle {
        pub fn area(r: f64) -> f64 {
            3.14159 * r * r
        }
    }
}

use shapes::circle;
use std::collections::HashMap;
use std::fmt::Result as FmtResult; // 用 as 取別名,避免名稱衝突

fn main() {
    println!("{:.2}", circle::area(2.0));
    let _map: HashMap<String, i32> = HashMap::new();
    let _ok: FmtResult = Ok(());
}

同一個路徑要引入多個名稱時可以合併,* 則引入全部(少用,容易造成名稱衝突):

use std::collections::{HashMap, HashSet};
use std::io::{self, Write};

fn main() {
    let _a: HashMap<i32, i32> = HashMap::new();
    let _b: HashSet<i32> = HashSet::new();
    io::stdout().flush().unwrap();
}

把模組拆成檔案

模組變大就拆成獨立檔案。在 main.rs 中寫 mod 名稱;(分號結尾),編譯器會去找對應檔案:

my_app/
├── Cargo.toml
└── src/
    ├── main.rs          # mod restaurant;
    ├── restaurant.rs    # 模組內容(不需要再包一層 mod)
    └── restaurant/
        └── kitchen.rs   # restaurant.rs 中宣告 pub mod kitchen;
// src/main.rs
mod restaurant;

fn main() {
    restaurant::serve();
}

使用外部 crate 與 workspace

外部 crate 以 cargo add 加入後,直接用 use 套件名::... 引入。專案大到需要多個相關套件時,可以用 workspace 把它們放在同一個倉庫、共用同一份 Cargo.locktarget/,做法見 The Cargo Book

實用心法

  • 先把所有東西放在 main.rs,覺得太長再拆,不必一開始就設計複雜的目錄。
  • 對外只公開必要的項目,其餘保持私有,日後修改內部實作比較安全。
  • 想寫可被其他專案重用的程式,使用 src/lib.rs,讓 main.rs 只負責呼叫它。

推薦影音

模組系統

簡述:Let's Get Rusty 依照官方書籍第 7 章製作,講解套件、crate、模組、路徑與 use,對應本頁全部內容。

下一頁:測試