如何使用 Cargo/Rust 在模块中包含同一目录中的文件?
How to include files from same directory in a module using Cargo/Rust?
我有一个 Cargo 项目,由同一目录中的三个文件组成:main.rs
、mod1.rs
和 mod2.rs
。
我想将函数从 mod2.rs
导入到 mod1.rs
,就像将函数从 mod1.rs
导入到 main.rs
一样。
我已经阅读了所需的文件结构,但我不明白 - 将所有导入的文件命名为 mod
会导致编辑器出现轻微混乱,而且这只会使项目层次结构复杂化。
有没有办法像在 Python 或 C++ 中那样独立于目录结构 import/include 文件?
main.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();
}
然后您可以 use crate::mod2
在 mod1
:
use crate::mod2;
pub fn mod1fn() {
println!("1");
mod2::mod2fn();
}
如果您还没有阅读 the chapter on modules in the new version of the Rust book,我建议您阅读 - 对于刚接触该语言的人来说,它们可能有点令人困惑。
如果你不希望你的 mod
语句全部在你的主文件中(例如:在 main.rs
中你不会在某些模块中使用一些 public 成员,在这个例如 mod2
) 您可以执行以下操作:
以这种方式构建您的 src
:
main.rs
my_module:
mod.rs
mod1.rs
mod2.rs
那么你可以 mod my_module
和 use my_module::mod1
,像这样:
main.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's answer的建议。
在src/lib.rs
/src/main.rs
/src/foo/mod.rs
中添加pub mod mod1; pub mod mod2;
。
b。使用 #[path]
main.rs
#[path = "./mod2.rs"]
mod mod2;
fn run() { mod2::mod2fn() }
为什么?
这是新 Rust 开发者的一个常见陷阱,这是可以理解的。
造成混淆的原因是 mod X
同一文件夹中文件的行为不一致。您可以在 lib.rs
中使用 mod X
,其中 显示为 导入与其相邻的文件,但您不能在 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
中,您在 top-level 模块中 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.rs
和mod.rs
是特殊的文件,它们的行为与目录中的其他文件。
它们将始终位于 parent 文件夹路径所描述的模块中(例如 src/foo/bar/mod.rs
= foo::bar
),而所有其他文件都属于它们自己的模块(src/foo/bar/baz.rs
= foo::bar::baz
).
乡村风格
Rust 对此有一些看法。
不再推荐使用 mod.rs
,这很好,因为它具有来自其兄弟姐妹的这种特殊行为。但是lib.rs
和main.rs
还是比较特别的
如果您想将测试与代码放在一起 (foo.rs
+ foo_test.rs
),建议您不要这样做。我不喜欢这样,所以我使用上面的 path
东西,我认为这对测试很好,因为它们不会导出到任何地方。必须在上面的模块中声明测试感觉不对,我也不喜欢必须使用 foo/test.rs
。
我有一个 Cargo 项目,由同一目录中的三个文件组成:main.rs
、mod1.rs
和 mod2.rs
。
我想将函数从 mod2.rs
导入到 mod1.rs
,就像将函数从 mod1.rs
导入到 main.rs
一样。
我已经阅读了所需的文件结构,但我不明白 - 将所有导入的文件命名为 mod
会导致编辑器出现轻微混乱,而且这只会使项目层次结构复杂化。
有没有办法像在 Python 或 C++ 中那样独立于目录结构 import/include 文件?
main.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();
}
然后您可以 use crate::mod2
在 mod1
:
use crate::mod2;
pub fn mod1fn() {
println!("1");
mod2::mod2fn();
}
如果您还没有阅读 the chapter on modules in the new version of the Rust book,我建议您阅读 - 对于刚接触该语言的人来说,它们可能有点令人困惑。
如果你不希望你的 mod
语句全部在你的主文件中(例如:在 main.rs
中你不会在某些模块中使用一些 public 成员,在这个例如 mod2
) 您可以执行以下操作:
以这种方式构建您的 src
:
main.rs
my_module:
mod.rs
mod1.rs
mod2.rs
那么你可以 mod my_module
和 use my_module::mod1
,像这样:
main.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's answer的建议。
在src/lib.rs
/src/main.rs
/src/foo/mod.rs
中添加pub mod mod1; pub mod mod2;
。
b。使用 #[path]
main.rs
#[path = "./mod2.rs"]
mod mod2;
fn run() { mod2::mod2fn() }
为什么?
这是新 Rust 开发者的一个常见陷阱,这是可以理解的。
造成混淆的原因是 mod X
同一文件夹中文件的行为不一致。您可以在 lib.rs
中使用 mod X
,其中 显示为 导入与其相邻的文件,但您不能在 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
中,您在 top-level 模块中 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.rs
和mod.rs
是特殊的文件,它们的行为与目录中的其他文件。
它们将始终位于 parent 文件夹路径所描述的模块中(例如 src/foo/bar/mod.rs
= foo::bar
),而所有其他文件都属于它们自己的模块(src/foo/bar/baz.rs
= foo::bar::baz
).
乡村风格
Rust 对此有一些看法。
不再推荐使用 mod.rs
,这很好,因为它具有来自其兄弟姐妹的这种特殊行为。但是lib.rs
和main.rs
还是比较特别的
如果您想将测试与代码放在一起 (foo.rs
+ foo_test.rs
),建议您不要这样做。我不喜欢这样,所以我使用上面的 path
东西,我认为这对测试很好,因为它们不会导出到任何地方。必须在上面的模块中声明测试感觉不对,我也不喜欢必须使用 foo/test.rs
。