文章目录

Rust 模块:mod 关键字与 pub 修饰符

发布于 2026-04-03 08:10:13 · 浏览 6 次 · 评论 0 条

Rust 模块:mod 关键字与 pub 修饰符

Rust 的模块系统用于组织代码,控制可见性,并避免命名冲突。核心机制由 mod 关键字和 pub 修饰符构成。掌握这两者,就能清晰地划分代码结构、封装内部逻辑,并安全地暴露接口。


创建模块:使用 mod 关键字

定义一个模块,在文件中使用 mod 关键字后跟模块名。

  1. 在当前文件内定义模块:直接用花括号包裹内容。

    mod network {
        fn connect() {
            println!("Connecting...");
        }
    }
  2. 从单独文件加载模块:省略花括号,Rust 会自动查找同名文件。

    • 假设主文件是 main.rslib.rs
    • 创建一个名为 network.rs 的文件。
    • 在主文件中写:mod network;
    • Rust 会自动加载 network.rs 的内容作为 network 模块。
  3. 从目录加载模块:当模块内容较多时,可将其放入目录。

    • 创建目录 network/
    • 在目录内创建 mod.rs 文件(这是该目录的入口)。
    • 在主文件中写:mod network;
    • Rust 会将 network/mod.rs 视为 network 模块的内容。

注意:从 Rust 2018 起,也可以不用 mod.rs,直接用 network/network.rs 配合 mod network;,但传统方式仍广泛使用。


控制可见性:使用 pub 修饰符

默认情况下,模块内的所有项(函数、结构体、常量等)都是私有的,外部无法访问。使用 pub 将项公开

  1. 公开单个项:在函数、结构体等前面加 pub

    mod math {
        pub fn add(a: i32, b: i32) -> i32 {
            a + b
        }
    
        fn internal_helper() {} // 私有,外部不可见
    }
  2. 公开整个模块:在 mod 前加 pub,使该模块可被父模块之外的代码引用。

    pub mod utils {
        pub fn log(msg: &str) {
            println!("{}", msg);
        }
    }
  3. 在其他模块中使用公开项

    • 通过路径访问:math::add(1, 2)
    • 或先引入作用域:use math::add;,然后直接调用 add(1, 2)

模块路径与 use 声明

Rust 使用路径来定位项,分为绝对路径(从 crate 根开始)和相对路径(从当前模块开始)。

  1. 绝对路径以 crate:: 开头

    crate::network::connect();
  2. 相对路径使用 self::super::

    • self:: 表示当前模块
    • super:: 表示父模块
      self::math::add(3, 4);
      super::config::get_port();
  3. 简化路径:使用 use 引入

    • 引入模块use network; → 可用 network::connect()
    • 引入具体项use network::connect; → 可直接调用 connect()
    • 引入多个项use math::{add, subtract};
    • 重命名use std::fmt::Result as FmtResult;

实际项目结构示例

假设你正在开发一个命令行工具,项目结构如下:

src/
├── main.rs
├── config.rs
└── utils/
    ├── mod.rs
    └── logger.rs
  1. main.rs 中声明模块

    mod config;
    mod utils;
    
    fn main() {
        let port = config::get_port();
        utils::logger::init();
    }
  2. config.rs 中公开函数

    pub fn get_port() -> u16 {
        8080
    }
  3. utils/mod.rs 中声明子模块并公开

    pub mod logger;
  4. utils/logger.rs 中定义公开函数

    pub fn init() {
        println!("Logger initialized");
    }

这样,main.rs 就能顺利调用 config::get_port()utils::logger::init()


pub 的进阶用法:选择性公开

pub 不仅可以完全公开,还能限制公开范围。

  1. pub(crate):仅在当前 crate 内公开,外部 crate 不可见。

    pub(crate) fn internal_api() {}
  2. pub(super):仅对父模块公开。

    pub(super) fn helper() {}
  3. pub(in path):仅在指定路径下公开。

    pub(in crate::network) fn debug_info() {}

这些修饰符帮助你在大型项目中精细控制封装边界,既保证内部协作,又防止外部误用。


常见错误与排查

  1. “cannot find function” 错误

    • 检查函数是否标记了 pub
    • 检查模块是否用 pub mod 声明(如果需要跨模块访问)
    • 检查 use 路径是否正确
  2. 模块文件未被加载

    • 确保在父模块中写了 mod xxx;
    • 文件名必须与模块名一致(如 mod db; 对应 db.rsdb/mod.rs
  3. 循环依赖

    • 避免模块 A 引用模块 B,同时模块 B 又引用模块 A
    • 解决方法:将共享类型提取到第三个模块,或使用 trait 抽象

最佳实践总结

场景 推荐做法
小型功能集合 单文件模块,用 mod { ... } 内联定义
独立组件(如网络、数据库) 单独 .rs 文件,配合 mod name;
复杂子系统 目录 + mod.rs 结构
公共 API 所有对外项必须加 pub,模块本身也需 pub mod
内部工具函数 不加 pub,保持私有

始终问自己:这个函数/类型是否需要被其他模块使用?只有答案是“是”,才加 pub。过度公开会增加维护成本,破坏封装性。

模块系统是 Rust 安全性和可维护性的基石。合理使用 modpub,你的代码将层次分明、边界清晰、易于测试和复用。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文