繁体   English   中英

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

[英]How to include files from same directory in a module using Cargo/Rust?

我有一个 Cargo 项目,由同一目录中的三个文件组成: main.rsmod1.rsmod2.rs

我想将函数从mod2.rs导入到mod1.rs ,就像我将函数从mod1.rs导入到main.rs
我已经阅读了所需的文件结构,但我不明白 - 将所有导入的文件命名为mod会导致编辑器中的轻微混乱,而且这只会使项目层次结构复杂化。

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

主.rs:

mod mod1; // Works

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}

mod1.rs:

mod mod2; // Fails

pub fn mod1fn() {
    println!("1");
    mod2::mod2fn();
}

mod2.rs:

pub fn mod2fn() {
    println!("2");
}

构建结果:

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;
  |     ^^^^

我无法use它,因为它在任何地方都不作为模块存在,而且我不想修改目录结构。

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

mod mod1;
mod mod2;

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}

然后你可以在mod1 use crate::mod2

use crate::mod2;

pub fn mod1fn() {
    println!("1");
    mod2::mod2fn();
}

如果您还没有阅读Rust 书的新版本中关于模块的章节,我建议您阅读 - 它们对于不熟悉该语言的人来说可能有点混乱。

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

以这种方式构建您的src

main.rs
my_module:
  mod.rs
  mod1.rs
  mod2.rs

那么你可以只修改mod my_moduleuse my_module::mod1 ,如下所示:

主.rs:

mod my_module;
use my_module::mod1;

fn main() {
    println!("Hello, world!");
    mod1::mod1fn();
}

my_module/mod.rs

pub mod mod1;
pub mod mod2;

my_module/mod1.rs

use super::mod2;

pub fn mod1fn() {
    println!("1");
    mod2::mod2fn();
}

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

一种。 在模块索引文件中定义模块

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

添加pub mod mod1; pub mod mod2; pub mod mod1; pub mod mod2; src/lib.rs / src/main.rs / src/foo/mod.rs

使用#[path]

主文件

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

fn run() { mod2::mod2fn() }

为什么?

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

混淆的原因来自于mod X对同一文件夹中文件的行为不一致。 您可以在lib.rs使用mod X ,这似乎会导入与其相邻的文件,但您不能在mod1.rsmod2.rs执行相同mod2.rs

每个文件的代码都属于一个模块。 文件模块的完整路径(例如foo::bar::baz )而不是文件的位置,决定了它如何解析mod X 你可以把它想象成每个模块都有一个固定的精神家园,但它可能在层次结构中定义了更src/lib.rs成员(例如src/lib.rs可能包含: mod foo { mod bar { pub fn hello() {} } } - 虽然你不能在lib.rs单独使用mod foo; )。

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

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

所以./mod1.rs所有代码都在crate::mod1模块中。

当您在./mod1.rs内调用use mod2 ,它会看到它在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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM