模組系統(Modules)#
模組(Module) 讓你將程式碼分組、控制可見性,並組織大型專案的結構。
Rust 的模組系統由三層構成: package(套件) 、 crate(包) 、 module(模組) 。
1. mod — 定義模組#
用 mod 關鍵字建立模組,可以巢狀:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| mod greetings {
pub fn hello() {
println!("你好!");
}
pub fn goodbye() {
println!("再見!");
}
}
fn main() {
greetings::hello(); // 你好!
greetings::goodbye(); // 再見!
}
|
2. pub — 控制可見性#
模組內所有項目預設是 私有的 ,只有加上 pub 才能從外部存取:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| mod auth {
pub struct User {
pub username: String,
password: String, // 私有欄位,外部無法直接存取
}
impl User {
pub fn new(username: &str, password: &str) -> User {
User {
username: String::from(username),
password: String::from(password),
}
}
pub fn is_valid(&self, password: &str) -> bool {
self.password == password // 私有欄位只能在模組內使用
}
}
}
fn main() {
let user = auth::User::new("alice", "secret123");
println!("用戶名:{}", user.username); // OK,公開欄位
// println!("{}", user.password); // 錯誤!私有欄位
println!("驗證:{}", user.is_valid("secret123")); // OK
}
|
super 與 self#
在模組內可以用 super 存取上一層,self 指向目前模組:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| mod outer {
pub fn greet() {
println!("外層");
}
pub mod inner {
pub fn greet() {
super::greet(); // 呼叫上一層的 greet
println!("內層");
}
}
}
fn main() {
outer::inner::greet();
}
|
3. use — 引入路徑#
每次都寫完整路徑很繁瑣,用 use 引入:
1
2
3
4
5
6
7
8
9
| mod greetings {
pub fn hello() { println!("你好!"); }
}
use greetings::hello;
fn main() {
hello(); // 不需要寫 greetings::hello()
}
|
引入多個項目#
1
| use std::collections::{HashMap, HashSet};
|
重新命名(as)#
1
2
3
4
5
6
| use std::collections::HashMap as Map;
fn main() {
let mut m: Map<&str, i32> = Map::new();
m.insert("a", 1);
}
|
pub use — 重新匯出#
讓外部使用者不必知道內部模組結構:
1
2
3
4
5
6
7
8
9
10
| mod shapes {
pub mod circle {
pub fn area(r: f64) -> f64 {
std::f64::consts::PI * r * r
}
}
}
// 將 circle::area 重新匯出,外部可直接用 shapes::area
pub use shapes::circle::area;
|
4. 多檔案模組#
實際專案中,模組通常分散在不同檔案。
目錄結構:
src/
├── main.rs
├── greetings.rs ← greetings 模組
└── math/
├── mod.rs ← math 模組入口
└── geometry.rs ← math::geometry 子模組
src/greetings.rs:
1
2
3
| pub fn hello(name: &str) {
println!("你好,{name}!");
}
|
src/math/mod.rs:
1
2
3
4
5
| pub mod geometry;
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
|
src/math/geometry.rs:
1
2
3
| pub fn circle_area(r: f64) -> f64 {
std::f64::consts::PI * r * r
}
|
src/main.rs:
1
2
3
4
5
6
7
8
9
10
11
| mod greetings;
mod math;
use greetings::hello;
use math::geometry::circle_area;
fn main() {
hello("Alice");
println!("圓面積:{:.2}", circle_area(3.0));
println!("加法:{}", math::add(1, 2));
}
|
現代 Rust(2018 Edition 後)也支援用同名目錄取代 mod.rs,例如將 math/mod.rs 改為 math.rs,效果相同。
5. Cargo 與套件管理#
Cargo.toml#
每個 Rust 專案由 Cargo.toml 管理。加入外部套件(crate):
1
2
3
| [dependencies]
serde = { version = "1", features = ["derive"] }
rand = "0.8"
|
執行 cargo add rand 可自動新增,然後 cargo build 下載並編譯。
使用外部套件範例#
1
2
3
| # Cargo.toml
[dependencies]
rand = "0.8"
|
1
2
3
4
5
6
7
| use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let n: u32 = rng.gen_range(1..=100);
println!("隨機數:{n}");
}
|
常用外部套件#
| 套件 | 用途 |
|---|
serde | JSON / YAML 序列化與反序列化 |
tokio | async 非同步執行環境 |
reqwest | HTTP 客戶端 |
clap | 命令列參數解析 |
anyhow | 簡化錯誤處理 |
rand | 隨機數產生 |
regex | 正規表達式 |
6. Crate 類型#
一個 Rust 套件(package)可以包含:
| 檔案 | 類型 | 說明 |
|---|
src/main.rs | binary crate | 可執行程式的入口 |
src/lib.rs | library crate | 函式庫,供其他程式引用 |
src/bin/*.rs | binary crate | 多個可執行程式 |
若要建立函式庫讓他人使用:
在 src/lib.rs 中定義公開介面,其他程式即可在 Cargo.toml 加入依賴後使用。
Reference#
https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html