Rust 组织管理
crate、module、`mod`/`pub`/`use`、以及文件与目录的映射。
Key Points`mod` 声明模块,`pub` 开放可见性,`use` 把路径引入当前作用域。
层级
| Term | Meaning |
|---|---|
| crate | 一次编译单元,一个二进制或一个库 |
| module | crate 内的命名空间,可嵌套 |
| path | crate::a::b / super::x / self::y |
| prelude | 自动导入的常用项 |
内联模块
Rust
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub mod advanced {
pub fn pow(base: i32, exp: u32) -> i32 {
base.pow(exp)
}
}
fn private_helper() {} // 默认私有
}
fn main() {
println!("{}", math::add(1, 2));
println!("{}", math::advanced::pow(2, 10));
// math::private_helper(); // 编译错误:私有
}Output
3
1024文件模块
Text
src/
├── main.rs ← crate 根
├── config.rs ← mod config;
├── db/
│ ├── mod.rs ← mod db; (旧写法)
│ └── query.rs ← mod query;
└── api/
├── mod.rs
└── user.rsRust
// main.rs
mod config;
mod db;
mod api;
fn main() {
println!("{}", config::PORT);
db::connect();
api::user::list();
}Rust
// db/mod.rs
pub mod query;
pub fn connect() {
println!("连接数据库");
}Rust
// db/query.rs
pub fn select_all() {
println!("查询全部");
}Output
8080
连接数据库
列出用户Since Rust 2018 you can use db.rs plus a db/ directory instead of mod.rs. Both are valid; new projects prefer the former since the file name matches the directory.
pub 的层级
Rust
mod outer {
pub mod inner {
pub fn public_fn() {}
pub(crate) fn crate_only() {}
pub(super) fn parent_only() {}
fn private_fn() {}
}
}
fn main() {
outer::inner::public_fn();
outer::inner::crate_only();
// outer::inner::private_fn(); // 不可见
}| Visibility | Scope |
|---|---|
| (默认) | 当前模块及其子模块 |
pub | 任何地方 |
pub(crate) | 当前 crate 内 |
pub(super) | 父模块 |
pub(in path) | 指定路径内 |
use
Rust
use std::collections::HashMap;
use std::fmt::{self, Display};
use std::io::prelude::*; // 导入 prelude
// 别名
use std::collections::HashMap as Map;
// 重导出:让别人从你的模块拿到它
pub use crate::internal::Helper;
// 分组
use std::{
fs,
path::{Path, PathBuf},
};
fn main() {
let mut m: Map<String, i32> = HashMap::new();
m.insert("a".into(), 1);
println!("{}", m.len());
let p = PathBuf::from("x");
println!("{}", p.display());
let _ = fs::metadata("x");
}Output
1
xpub use is the key to a good public API: keep implementation in an internal module and re-export the types at the top level, so internal refactors never break callers' use paths.工作区与 crate 类型
Text
workspace/
├── Cargo.toml [workspace] members = [...]
├── core/ lib crate(库)
│ └── src/lib.rs
└── cli/ bin crate(可执行)
└── src/main.rsTOML
# cli/Cargo.toml
[dependencies]
core = { path = "../core" }A crate can be both: with src/lib.rs and src/main.rs together, main.rs can use the library of the same name. Handy when you want a reusable library plus a CLI.
层级
| 术语 | 含义 |
|---|---|
| crate | 一次编译单元,一个二进制或一个库 |
| module | crate 内的命名空间,可嵌套 |
| path | crate::a::b / super::x / self::y |
| prelude | 自动导入的常用项 |
内联模块
Rust
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub mod advanced {
pub fn pow(base: i32, exp: u32) -> i32 {
base.pow(exp)
}
}
fn private_helper() {} // 默认私有
}
fn main() {
println!("{}", math::add(1, 2));
println!("{}", math::advanced::pow(2, 10));
// math::private_helper(); // 编译错误:私有
}Output
3
1024文件模块
Text
src/
├── main.rs ← crate 根
├── config.rs ← mod config;
├── db/
│ ├── mod.rs ← mod db; (旧写法)
│ └── query.rs ← mod query;
└── api/
├── mod.rs
└── user.rsRust
// main.rs
mod config;
mod db;
mod api;
fn main() {
println!("{}", config::PORT);
db::connect();
api::user::list();
}Rust
// db/mod.rs
pub mod query;
pub fn connect() {
println!("连接数据库");
}Rust
// db/query.rs
pub fn select_all() {
println!("查询全部");
}Output
8080
连接数据库
列出用户Rust 2018 起还可以用 db.rs + db/ 目录的写法,不必写 mod.rs。两种都合法,新项目推荐后者(文件名和目录名一致,编辑器里更好找)。
pub 的层级
Rust
mod outer {
pub mod inner {
pub fn public_fn() {}
pub(crate) fn crate_only() {}
pub(super) fn parent_only() {}
fn private_fn() {}
}
}
fn main() {
outer::inner::public_fn();
outer::inner::crate_only();
// outer::inner::private_fn(); // 不可见
}| 可见性 | 范围 |
|---|---|
| (默认) | 当前模块及其子模块 |
pub | 任何地方 |
pub(crate) | 当前 crate 内 |
pub(super) | 父模块 |
pub(in path) | 指定路径内 |
use
Rust
use std::collections::HashMap;
use std::fmt::{self, Display};
use std::io::prelude::*; // 导入 prelude
// 别名
use std::collections::HashMap as Map;
// 重导出:让别人从你的模块拿到它
pub use crate::internal::Helper;
// 分组
use std::{
fs,
path::{Path, PathBuf},
};
fn main() {
let mut m: Map<String, i32> = HashMap::new();
m.insert("a".into(), 1);
println!("{}", m.len());
let p = PathBuf::from("x");
println!("{}", p.display());
let _ = fs::metadata("x");
}Output
1
xpub use 是设计公共 API 的关键:内部实现放在 internal 模块,对外用 pub use 把类型「搬」到顶层。这样重构内部结构不会破坏使用者的 use 路径。工作区与 crate 类型
Text
workspace/
├── Cargo.toml [workspace] members = [...]
├── core/ lib crate(库)
│ └── src/lib.rs
└── cli/ bin crate(可执行)
└── src/main.rsTOML
# cli/Cargo.toml
[dependencies]
core = { path = "../core" }一个 crate 可以同时是库和二进制:src/lib.rs + src/main.rs 共存时,main.rs 会自动 use 到同名的库。这在「既想给别人用,又想提供命令行」时很方便。