Rust 中的模块:如何将代码拆分成多个文件而不抓狂

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

当一个文件已经不够用时

\n\n

你在用 Rust 编程。你的项目在不断增长。昨天 main.rs 还能容纳一切——函数、结构体、几个配置。而今天,你要花五分钟才能在数千行代码中找到需要的函数。熟悉吗?

\n\n

迟早,每个 Rust 开发者都会遇到将代码拆分成逻辑部分的需求。看起来能有多难?创建文件夹,放入文件,导入——就完成了。但 Rust 的模块系统以其严格性著称。在 mod.rs 中写错一处,编译器就会抛出一个你需要花半小时才能解开的错误。

\n\n

在本文中,我们将分析 将 Rust 模块拆分成多个文件时的常见错误,更重要的是,展示如何避免它们。你将了解如何正确组织文件结构,何时使用 mod.rs,何时使用 lib.rs,以及为什么 pub use 是你最好的朋友。

\n\n

Rust 模块系统的剖析

\n\n

在深入探讨错误之前,让我们回顾一下基础知识。在 Rust 中,模块是代码组织的单元。默认情况下,每个文件都是一个模块,但事情并非如此简单。

\n\n

有两种方法:

\n\n
    \n
  • 同名文件模块:如果你在 lib.rs 或 main.rs 中声明 mod utils;,文件 utils.rs 会自动成为模块 utils。
  • \n
  • 目录模块:一个包含 mod.rs 文件的 utils/ 文件夹。在这种情况下,mod.rs 是模块的入口点。
  • \n
\n\n

听起来很简单,但正是这里隐藏着大多数陷阱。让我们来分析最常见的那些。

\n\n

将模块拆分成多个文件时的 5 大错误

\n\n

错误 #1:忘记声明子模块

\n\n

你创建了文件 network/tcp.rs 并尝试使用它。你写 use network::tcp;——然后得到一个编译错误。为什么?因为 Rust 不会自动扫描文件夹。你必须显式声明每个子模块。

\n\n
// network/mod.rs\n// ❌ 错误:子模块 tcp 未声明\n// use network::tcp; // 无法编译\n\n// ✅ 正确做法:\npub mod tcp; // 声明子模块\n
\n\n

如何避免:始终检查你是否在父模块中添加了 pub mod 子模块名;。这类似于显式导入——Rust 要求明确性。

\n\n

错误 #2:混淆 mod.rs 和 lib.rs

\n\n

新手经常将 mod.rs 放在项目根目录,与 main.rs 并列。这能工作,但仅当你创建库时。对于可执行文件 (main.rs),根模块就是 main.rs 本身。而 mod.rs 是文件夹内的文件。

\n\n
my_project/\n├── main.rs        // 二进制文件的根模块\n├── lib.rs         // 库的根模块(如果有)\n├── utils/\n│   ├── mod.rs     // 模块 utils 的入口点\n│   └── helpers.rs\n
\n\n

如何避免:记住规则:mod.rs 只存在于模块文件夹内。如果你需要库的根模块——使用 lib.rs。

\n\n

错误 #3:忘记在子模块中使用 pub

\n\n

你声明了子模块,但仍然无法调用函数。很可能,你忘了指定 pub。

\n\n
// network/mod.rs\npub mod tcp;\n\n// network/tcp.rs\n// ❌ 函数默认是私有的\nfn connect() { /* ... */ }\n\n// ✅ 使其公开\npub fn connect() { /* ... */ }\n
\n\n

在 Rust 中,所有内容默认都是私有的。这不是 bug,而是特性:你自己决定向外部世界开放什么。如果函数需要在模块外部使用——加上 pub。

\n\n

如何避免:有意识地使用 pub。对于内部工具,保持私有访问。对于 API,使其公开。

\n\n

错误 #4:忽略

博客

书籍推荐