如何使用Cargo/Rust在模块中包含同一目录中的文件?

Neo*_*Neo 7 import module rust rust-cargo

我有一个货物项目包括三个文件在同一目录下:main.rs,mod1.rsmod2.rs.

我想从导入功能mod2.rs,以mod1.rs同样的方式,我会从导入功能mod1.rsmain.rs.
我已经阅读了所需的文件结构但我没有得到它 - 命名所有导入的文件mod将导致编辑器中的轻微混淆,这也只是使项目层次结构复杂化.

有没有像在Python或C++中那样独立于目录结构导入/包含文件的方法?

main.rs:

mod mod1; // Works

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}
Run Code Online (Sandbox Code Playgroud)

mod1.rs:

mod mod2; // Fails

pub fn mod1fn() {
    println!("1");
    mod2::mod2fn();
}
Run Code Online (Sandbox Code Playgroud)

mod2.rs:

pub fn mod2fn() {
    println!("2");
}
Run Code Online (Sandbox Code Playgroud)

建立结果:

error: cannot declare a new module at this location
 --> src\mod1.rs:1:5
  |
1 | mod mod2;
  |     ^^^^
  |
note: maybe move this module `src` to its own directory via `src/mod.rs`
 --> src\mod1.rs:1:5
  |
1 | mod mod2;
  |     ^^^^
note: ... or maybe `use` the module `mod2` instead of possibly redeclaring it
 --> src\mod1.rs:1:5
  |
1 | mod mod2;
  |     ^^^^
Run Code Online (Sandbox Code Playgroud)

我不能use,因为它不存在于任何地方的模块,我不想修改目录结构.

Joe*_*lay 11

所有顶级模块声明都应该进入main.rs,如下所示:

mod mod1;
mod mod2;

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}
Run Code Online (Sandbox Code Playgroud)

你可以use crate::mod2在里面mod1:

use crate::mod2;

pub fn mod1fn() {
    println!("1");
    mod2::mod2fn();
}
Run Code Online (Sandbox Code Playgroud)

我建议你阅读新版Rust书中的模块一章,如果你还没有 - 对于那些不熟悉该语言的人来说,它们会有点混乱.

  • 非常感谢!我几乎肯定没有这样的选择. (2认同)
  • 我读了那章,但是不明白我能做你所描述的。 (2认同)

vau*_*han 8

每个文件都是一个模块,如果不创建新的嵌套模块,则无法导入另一个文件。

A。在模块索引文件中定义模块

正如@giuliano-oliveira 的回答所建议的。

加入/ / 。pub mod mod1; pub mod mod2;src/lib.rssrc/main.rssrc/foo/mod.rs

b. 使用#[path]

主程序.rs

#[path = "./mod2.rs"]
mod mod2;

fn run() { mod2::mod2fn() }
Run Code Online (Sandbox Code Playgroud)

为什么?

对于新的 Rust 开发人员来说,这是一个常见的陷阱,这是可以理解的。

mod X造成混乱的原因是同一文件夹中的文件行为不一致。您可以使用mod Xinlib.rs出现导入与其相邻的文件,但不能在mod1.rs或 中执行相同的操作mod2.rs

每个文件的代码都属于一个模块。文件模块的完整路径(例如foo::bar::baz)而不是文件的位置决定了它的解析方式mod X。您可以将其视为每个模块都有一个固定的精神家园,但它可能具有在层次结构中进一步定义的成员(例如src/lib.rs可能包含:mod foo { mod bar { pub fn hello() {} } }- 尽管这样您不能mod foo;单独使用lib.rs)。

在 中main.rs,您位于顶级模块中crate

mod mod1;创建一个新模块mod1,并将 的内容添加./mod1.ts到该模块中。

所以里面的所有代码都./mod1.rscrate::mod1模块内部。

当你调用use mod2inside时./mod1.rs,它​​会发现它在 inside crate::mod1,其精神家园目录为src/mod1,并查找:

  • src/mod1/mod2.rs
  • src/mod1/mod2/mod.rs

复杂性来自于允许模块既是目录又是文件,而不是强制每个模块是它自己的目录(可能试图避免 Java 文件夹结构),这会消除歧义。

要记住的关键是 和lib.rsmod.rs特殊文件,其行为与目录中的其他文件不同。

src/foo/bar/mod.rs它们将始终位于父文件夹路径(例如= )描述的模块中foo::bar,而所有其他文件都属于它们自己的模块(src/foo/bar/baz.rs= foo::bar::baz)。

乡村之路

Rust对此有一些看法。

mod.rs不再推荐使用,这很好,因为它具有来自其兄弟姐妹的特殊行为。但lib.rsmain.rs仍然很特别。

如果您想将测试与代码 ( foo.rs+ foo_test.rs) 放在一起,建议您不要这样做。我不喜欢这个,所以我使用path上面的东西,我认为这对于测试来说很好,因为它们不会导出到任何地方。必须在上面的模块中声明测试感觉是错误的,而且我也不喜欢使用foo/test.rs其中任何一个。

  • 当您的答案内容相反时,使用 **“使用 #[path]”** 作为大粗体标题会给浏览者留下错误的印象。我个人会完全避免提及它。 (3认同)

llp*_*kio 7

如果您不希望mod所有语句都在主文件中(例如:main.rs您不会在某个模块中使用某些公共成员,在本例中是mod2),您可以执行以下操作:

src这样构建你的:

main.rs
my_module:
  mod.rs
  mod1.rs
  mod2.rs
Run Code Online (Sandbox Code Playgroud)

那么你可以mod my_moduleuse my_module::mod1这样:

主要.rs:

main.rs
my_module:
  mod.rs
  mod1.rs
  mod2.rs
Run Code Online (Sandbox Code Playgroud)

my_module/mod.rs

pub mod mod1;
pub mod mod2;
Run Code Online (Sandbox Code Playgroud)

my_module/mod1.rs

mod my_module;
use my_module::mod1;

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}
Run Code Online (Sandbox Code Playgroud)