x-i18n: generated_at: “2026-03-01T13:55:41Z” model: gemini-3-flash-preview provider: google-gemini-cli source_hash: f71fdf4512195e4c048c6b9c89e5575fea219332099660464e1b2a279f9d5782 source_path: ch07-05-separating-modules-into-different-files.md workflow: 16
将模块拆分为不同的文件 (Separating Modules into Different Files)
Separating Modules into Different Files
到目前为止,本章中的所有示例都在一个文件中定义了多个模块。当模块变大时,你可能希望将其定义移动到单独的文件中,以使代码更易于导航。
So far, all the examples in this chapter defined multiple modules in one file. When modules get large, you might want to move their definitions to a separate file to make the code easier to navigate.
例如,让我们从示例 7-17 中的代码开始,该代码有多个餐厅模块。我们将把模块提取到文件中,而不是在 crate 根文件中定义所有模块。在这种情况下,crate 根文件是 src/lib.rs,但此过程也适用于 crate 根文件为 src/main.rs 的二进制 crate。
For example, let’s start from the code in Listing 7-17 that had multiple restaurant modules. We’ll extract modules into files instead of having all the modules defined in the crate root file. In this case, the crate root file is src/lib.rs, but this procedure also works with binary crates whose crate root file is src/main.rs.
首先,我们将 front_of_house 模块提取到它自己的文件中。删除 front_of_house 模块花括号内的代码,仅保留 mod front_of_house; 声明,使 src/lib.rs 包含示例 7-21 所示的代码。请注意,在我们在示例 7-22 中创建 src/front_of_house.rs 文件之前,这段代码将无法编译。
First, we’ll extract the front_of_house module to its own file. Remove the
code inside the curly brackets for the front_of_house module, leaving only
the mod front_of_house; declaration, so that src/lib.rs contains the code
shown in Listing 7-21. Note that this won’t compile until we create the
src/front_of_house.rs file in Listing 7-22.
{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs}}
接下来,将花括号中的代码放入名为 src/front_of_house.rs 的新文件中,如示例 7-22 所示。编译器知道要查找这个文件,因为它在 crate 根中遇到了名为 front_of_house 的模块声明。
Next, place the code that was in the curly brackets into a new file named
src/front_of_house.rs, as shown in Listing 7-22. The compiler knows to look
in this file because it came across the module declaration in the crate root
with the name front_of_house.
{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/front_of_house.rs}}
请注意,在模块树中,你只需要使用 mod 声明加载一个文件“一次”。一旦编译器知道该文件是项目的一部分(并且由于你放置 mod 语句的位置,它知道了代码在模块树中的位置),项目中的其他文件应该使用指向声明位置的路径来引用已加载文件的代码,如“在模块树中引用项的路径”部分所述。换句话说,mod “不是”你在其他编程语言中可能见到的“include”操作。
Note that you only need to load a file using a mod declaration once in your
module tree. Once the compiler knows the file is part of the project (and knows
where in the module tree the code resides because of where you’ve put the mod
statement), other files in your project should refer to the loaded file’s code
using a path to where it was declared, as covered in the “Paths for Referring
to an Item in the Module Tree” section. In other words,
mod is not an “include” operation that you may have seen in other
programming languages.
接下来,我们将 hosting 模块提取到它自己的文件中。过程略有不同,因为 hosting 是 front_of_house 的子模块,而不是根模块的子模块。我们将把 hosting 的文件放在一个新目录中,该目录将以其在模块树中的祖先命名,在此例中为 src/front_of_house。
Next, we’ll extract the hosting module to its own file. The process is a bit
different because hosting is a child module of front_of_house, not of the
root module. We’ll place the file for hosting in a new directory that will be
named for its ancestors in the module tree, in this case src/front_of_house.
要开始移动 hosting,我们将 src/front_of_house.rs 更改为仅包含 hosting 模块的声明:
To start moving hosting, we change src/front_of_house.rs to contain only
the declaration of the hosting module:
{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house.rs}}
然后,我们创建一个 src/front_of_house 目录和一个 hosting.rs 文件,以包含在 hosting 模块中所做的定义:
Then, we create a src/front_of_house directory and a hosting.rs file to
contain the definitions made in the hosting module:
{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house/hosting.rs}}
如果我们转而将 hosting.rs 放在 src 目录中,编译器会期望 hosting.rs 的代码位于在 crate 根中声明的 hosting 模块中,而不是被声明为 front_of_house 模块的子模块。编译器关于检查哪些文件对应哪些模块代码的规则意味着目录和文件能更好地匹配模块树。
If we instead put hosting.rs in the src directory, the compiler would
expect the hosting.rs code to be in a hosting module declared in the crate
root and not declared as a child of the front_of_house module. The
compiler’s rules for which files to check for which modules’ code mean the
directories and files more closely match the module tree.
备选文件路径 (Alternate File Paths)
Alternate File Paths
到目前为止,我们已经介绍了 Rust 编译器使用的最惯用的文件路径,但 Rust 也支持旧风格的文件路径。对于在 crate 根中声明的名为
front_of_house的模块,编译器将在以下位置查找该模块的代码:So far we’ve covered the most idiomatic file paths the Rust compiler uses, but Rust also supports an older style of file path. For a module named
front_of_housedeclared in the crate root, the compiler will look for the module’s code in:
- src/front_of_house.rs(我们介绍过的)
- src/front_of_house/mod.rs(旧风格,仍支持的路径)
对于作为
front_of_house子模块的名为hosting的模块,编译器将在以下位置查找该模块的代码:For a module named
hostingthat is a submodule offront_of_house, the compiler will look for the module’s code in:
- src/front_of_house/hosting.rs(我们介绍过的)
- src/front_of_house/hosting/mod.rs(旧风格,仍支持的路径)
如果你对同一个模块同时使用两种风格,你将得到一个编译器错误。在同一个项目中的不同模块混用两种风格是允许的,但可能会让导航你项目的人感到困惑。
If you use both styles for the same module, you’ll get a compiler error. Using a mix of both styles for different modules in the same project is allowed but might be confusing for people navigating your project.
使用名为 mod.rs 文件的主要缺点是你的项目最终可能会有很多名为 mod.rs 的文件,当你同时在编辑器中打开它们时,这可能会变得很混乱。
The main downside to the style that uses files named mod.rs is that your project can end up with many files named mod.rs, which can get confusing when you have them open in your editor at the same time.
我们已经将每个模块的代码移动到了单独的文件中,模块树保持不变。eat_at_restaurant 中的函数调用将无需任何修改即可工作,尽管定义位于不同的文件中。这种技术让你可以随着模块规模的增长将其移动到新文件中。
We’ve moved each module’s code to a separate file, and the module tree remains
the same. The function calls in eat_at_restaurant will work without any
modification, even though the definitions live in different files. This
technique lets you move modules to new files as they grow in size.
请注意,src/lib.rs 中的 pub use crate::front_of_house::hosting 语句也没有改变,use 对哪些文件作为 crate 的一部分被编译也没有任何影响。mod 关键字声明模块,而 Rust 会在与模块同名的文件中查找进入该模块的代码。
Note that the pub use crate::front_of_house::hosting statement in
src/lib.rs also hasn’t changed, nor does use have any impact on what files
are compiled as part of the crate. The mod keyword declares modules, and Rust
looks in a file with the same name as the module for the code that goes into
that module.
总结 (Summary)
Summary
Rust 允许你将一个包拆分为多个 crate,并将一个 crate 拆分为模块,以便你可以从另一个模块中引用一个模块中定义的项。你可以通过指定绝对或相对路径来实现这一点。这些路径可以通过 use 语句引入作用域,以便你可以在该作用域内多次使用该项时使用较短的路径。模块代码默认是私有的,但你可以通过添加 pub 关键字使定义成为公有的。
Rust lets you split a package into multiple crates and a crate into modules so
that you can refer to items defined in one module from another module. You can
do this by specifying absolute or relative paths. These paths can be brought
into scope with a use statement so that you can use a shorter path for
multiple uses of the item in that scope. Module code is private by default, but
you can make definitions public by adding the pub keyword.
在下一章中,我们将研究标准库中的一些集合数据结构,你可以在你整齐组织的代码中使用它们。
In the next chapter, we’ll look at some collection data structures in the standard library that you can use in your neatly organized code.