在 Rust 中,mod.rs 文件的目的是什么



在我见过的一些 Rust 项目(即 pczarn/rustboot(中,无论出于何种原因,我都看到了目录中mod.rs文件。我无法找到有关此的文档,并且在许多其他 Rust 项目中都看到了它。mod.rs 文件的用途是什么,我应该什么时候使用它?

想象一下以下目录结构:

法典/ '——main.rs   -东西/    '- mod.rs

如果在main.rs中你执行mod something;,那么它将在something/mod.rs文件中查找以用作something模块声明的内容。

另一种方法是在 code/ 目录中有一个something.rs文件。

所以回顾一下,当你编写一个空的模块声明,如 mod something; ,它看起来要么:

  • 同一目录中名为 something.rs 的文件
  • 同一目录中名为 something 的文件夹中名为 mod.rs
  • 的文件

然后,它使用其中任一文件的内容用作模块声明的内容。

模块对于理解很重要,但我发现大多数文档经常让你在这个问题上挠头。

来自Python还是Javascript

粗略地说,mod.rs有点像python中的__init__.py或javascript中的index.js。但只是一种。这在 Rust 中有点复杂。

生锈是不同的

文件夹还没有立即准备好在 Rust 中用作模块。

您必须在文件夹中添加一个名为 mod.rs 的文件,以公开一个名为该文件夹的新模块。mod.rs中的代码是该模块的内容。文件夹中的所有其他文件可能依次作为子模块公开(更多内容见下文(。

等等,还有另一种方法

您也可以使用与文件夹级别相同的文件,并以该文件夹命名 ( <folder_name>.rs (。

这是自 rustc 1.30 以来的首选方式。(评论中感谢马库斯托曼(

来自 Rust 参考:

注意:在 rustc 1.30 之前,使用 mod.rs 文件是加载的方式具有嵌套子项的模块。鼓励使用新的命名约定,因为它更一致,并避免了许多项目中名为 mod.rs 的文件。

完整示例

src
    utils
        bar.rs
        foo.rs
    main.rs

此时,编译器不知道src/utils/foo.rssrc/utils/bar.rs

首先,您必须公开src/utils/ 。如上所示,您有 2 个选项:

  • 添加文件:src/utils/mod.rs
  • 添加文件src/utils.rs(名称与文件夹完全相同,不带扩展名(

现在,相对于 src 文件夹(又名 crate 级别(,可以使用一个名为 utils 的模块。

其次,您必须公开文件src/utils/foo.rssrc/utils/bar.rs

为此,utils模块必须声明 2 个以这些文件命名的新子模块。所以src/utils/mod.rs(或src/utils.rs(的内容应该是:

pub mod bar;
pub mod foo;

现在,这两个文件中公开的任何内容都可以在其他模块中使用! 🎉

你可以用src/main.rs写以下内容:

mod utils;
use utils::{foo, bar};

生成的文件结构

选项 1 • mod.rs (旧方式(:

src
    utils
        bar.rs
        foo.rs
        mod.rs
    main.rs

选项 2 • <folder_name>.rs (首选方式(:

src
    utils
        bar.rs
        foo.rs
    utils.rs
    main.rs

<小时 />

有关模块工作原理的更多高级详细信息

这仍然是一个表面的解释,你的下一个目的地是官方文档 🧑 🎓

还有第三种声明模块(核心语言(的方法:

mod utils {
  // module code goes here. That's right, inside of the file.
}

但也有可能只写mod utils;.在这种情况下,如上所示,Rust 知道搜索src/utils.rssrc/utils/mod.rs中的任何一个。

看,当您尝试在文件中使用模块(例如src/main.rs(,您可以通过以下方式引用它:

  • 从内部:src/main.rs
    • mod module { ... }
  • 从内部嵌套模块:src/main.rs
    • mod module { pub mod sub_module { ... } }
  • 从 sybling 文件: src/*.rs
  • mod.rs 个文件夹中的文件:src/*/mod.rs
  • (以及上述的无限递归组合(

包含mod.rs的文件或文件夹不会成为模块。
相反,Rust 语言允许您使用文件层次结构组织模块(语言功能(。

真正有趣的是,您可以自由地将所有方法混合在一起。

例如,您可能认为不能直接从main.rs引用src/utils/foo.rs
但您可以:

// src/main.rs
mod utils {
  pub mod foo;
}

重要提示

  • 在文件中声明的模块将始终优先(因为实际上您永远不需要搜索文件层次结构(
  • 您不能使用其他 2 种方法来引用同一模块

例如,同时具有 src/utils.rssrc/utils/mod.rs 将在编译时引发以下错误:

error[E0761]: file for module `utils` found at both "src/utils.rs" and "src/utils/mod.rs"
 --> src/main.rs:1:1
  |
1 | mod utils;
  | ^^^^^^^^^^
  |
  = help: delete or rename one of them to remove the ambiguity

让我们总结一下。模块向编译器公开:

  • 从上到下
  • 仅供参考(这就是为什么在模块"导入"之前你没有智能感知的原因(
  • 从入口点开始(默认情况下src/main.rssrc/lib.rs。但它可能是您在 Cargo.toml 中配置的任何内容。然而,这与这个问题关系不大(

通过我们之前的示例,我们按顺序排列:

  1. src/main.rs -> crate

    因为crate模块包含我们接下来得到mod utils;

  2. src/utils.rssrc/utils/mod.rs -> crate::utils

    因为utils模块包含我们接下来得到的mod foo;

  3. src/utils/foo.rs -> crate::utils::foo

除了始终与crate模块匹配的 lib.rs 和 main.rs 之外,每个rs文件都有自己的模块。

只有一种方法可以声明模块:

/* pub */ mod sub_module1;
模块不能在根/crate 模块树之外声明(即,在模块树中,子模块必须始终

具有直接在lib.rsmain.rs中声明的父模块,因此第一个程序子模块必须始终在那里声明 - 树数据结构,如果还不够明显(。

有两种方法可以将模块嵌套在声明模块的模块中:

  • <module_where_it_is_declared>/<module_name.rs>
  • <module_where_it_is_declared>/module_name/mod.rs

如果module_where_it_is_declared是 crate 模块,则不需要这个相应的子文件夹(从上面的方案中消失(。

下面是一个示例,对 lib 和二进制板条箱都有效:

src
|---lib.rs ( contains: pub mod b2; )
|---b2.rs ( contains: pub mod bb2; )
|---b2
|   |---bb2.rs
.   .

或者:

src
|---lib.rs ( contains: pub mod b2; )
|---b2
|   |---mod.rs ( contains: pub mod bb2; )
|   |---bb2.rs
.   .

你可以看到你可以混合和匹配(b2使用mod.rs方式,bb2使用"文件"方式(。

以下是仅使用同样有效的文件模式的方法:

src
|---lib.rs ( contains: pub mod b2; )
|---b2.rs ( contains: pub mod bb2; )
|---b2
|   |---bb2.rs (contains: pub mod bbb2; )
|   |---bbb2.rs (contains: pub mod bbbb2; )
|   |---bbb2
|   |   |---bbbb2.rs
.   .   .

我想这取决于你想如何嵌套模块。

我喜欢只导出其他子模块并且其中没有任何其他(或很少(代码的模块的mod.rs语法,尽管您可以将任何您想要的内容放入mod.rs.

我使用类似于 JS/TS 世界中的桶模式mod.rs将多个子模块汇总到单个父模块中。

另外不要忘记,可以通过添加作用域块来内联定义(不仅是声明(模块:

pub mod my_submodule {
    // ...
}

相关内容

  • 没有找到相关文章

最新更新