Rust 组织管理

crate、module、`mod`/`pub`/`use`、以及文件与目录的映射。

Intermediate
Key Points`mod` 声明模块,`pub` 开放可见性,`use` 把路径引入当前作用域。

层级

TermMeaning
crate一次编译单元,一个二进制或一个库
modulecrate 内的命名空间,可嵌套
pathcrate::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.rs
Rust
// 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();   // 不可见
}
VisibilityScope
(默认)当前模块及其子模块
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
x
pub 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.rs
TOML
# 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.

Friends & Partners