简体   繁体   English

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

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

I have a Cargo project consisting of three files in the same directory: main.rs , mod1.rs and mod2.rs .我有一个 Cargo 项目,由同一目录中的三个文件组成: main.rsmod1.rsmod2.rs

I want to import functions from mod2.rs to mod1.rs the same way I would import functions from mod1.rs to main.rs .我想将函数从mod2.rs导入到mod1.rs ,就像我将函数从mod1.rs导入到main.rs
I've read about the file structure required but I don't get it - naming all the imported files mod will lead to minor confusion in the editor and also this just complicates the project hierarchy.我已经阅读了所需的文件结构,但我不明白 - 将所有导入的文件命名为mod会导致编辑器中的轻微混乱,而且这只会使项目层次结构复杂化。

Is there a way to import/include files independently of directory structure as I would in Python or C++?有没有办法像在 Python 或 C++ 中那样独立于目录结构导入/包含文件?

main.rs:主.rs:

mod mod1; // Works

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

mod1.rs: mod1.rs:

mod mod2; // Fails

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

mod2.rs: mod2.rs:

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

Building results in:构建结果:

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

I can't use it as it doesn't exist as a module anywhere, and I don't want to modify the directory structure.我无法use它,因为它在任何地方都不作为模块存在,而且我不想修改目录结构。

All of your top level module declarations should go in main.rs , like so:所有顶级模块声明都应该放在main.rs ,如下所示:

mod mod1;
mod mod2;

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

You can then use crate::mod2 inside mod1 :然后你可以在mod1 use crate::mod2

use crate::mod2;

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

I'd recommend reading the chapter on modules in the new version of the Rust book if you haven't already - they can be a little confusing for people who are new to the language.如果您还没有阅读Rust 书的新版本中关于模块的章节,我建议您阅读 - 它们对于不熟悉该语言的人来说可能有点混乱。

If you don't want your mod statements all in your main file (eg: in main.rs you won't use some public members inside some module, in this example it is mod2 ) you can do the following:如果你不希望你的mod语句都在你的主文件中(例如:在main.rs你不会在某个模块中使用一些公共成员,在这个例子中它是mod2 )你可以执行以下操作:

structure your src this way:以这种方式构建您的src

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

then you can just mod my_module and use my_module::mod1 , like so:那么你可以只修改mod my_moduleuse my_module::mod1 ,如下所示:

main.rs:主.rs:

mod my_module;
use my_module::mod1;

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

my_module/mod.rs my_module/mod.rs

pub mod mod1;
pub mod mod2;

my_module/mod1.rs my_module/mod1.rs

use super::mod2;

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

Every file is a module and cannot import another without creating a new nested module.每个文件都是一个模块,如果不创建新的嵌套模块,就不能导入另一个文件。

a.一种。 Define modules in module index file在模块索引文件中定义模块

As @giuliano-oliveira's answer recommends.正如@giuliano-oliveira 的回答所建议的那样。

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

b.Use #[path]使用#[path]

main.rs主文件

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

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

Why?为什么?

This is a common pitfall for new Rust devs and understandably so.对于新的 Rust 开发人员来说,这是一个常见的陷阱,这是可以理解的。

The reason for the confusion comes from an inconsistency in behavior of mod X for files in the same folder.混淆的原因来自于mod X对同一文件夹中文件的行为不一致。 You can use mod X in lib.rs which appears to import a file adjacent to it, but you can't do the same in mod1.rs or mod2.rs .您可以在lib.rs使用mod X ,这似乎会导入与其相邻的文件,但您不能在mod1.rsmod2.rs执行相同mod2.rs

The code of every file belongs to a module.每个文件的代码都属于一个模块。 The full path of the file's module (eg foo::bar::baz ) rather than the location of the file, determines how it resolves mod X .文件模块的完整路径(例如foo::bar::baz )而不是文件的位置,决定了它如何解析mod X You can think of it as every module having a fixed spiritual home, but it may have members defined further up in the hierarchy (eg src/lib.rs might contain: mod foo { mod bar { pub fn hello() {} } } - although then you cannot use mod foo; alone in lib.rs ).你可以把它想象成每个模块都有一个固定的精神家园,但它可能在层次结构中定义了更src/lib.rs成员(例如src/lib.rs可能包含: mod foo { mod bar { pub fn hello() {} } } - 虽然你不能在lib.rs单独使用mod foo; )。

In main.rs , you are in the top-level module crate .main.rs ,您位于顶级模块crate

mod mod1; creates a new module mod1 , and adds the contents of ./mod1.ts to that module.创建一个新的模块mod1 ,并增加内容./mod1.ts该模块。

So all code inside ./mod1.rs is inside the crate::mod1 module.所以./mod1.rs所有代码都在crate::mod1模块中。

When you call use mod2 inside ./mod1.rs , it sees that it is inside crate::mod1 , whose spiritual home dir is src/mod1 , and looks for either:当您在./mod1.rs内调用use mod2 ,它会看到它在crate::mod1 ,其精神主目录为src/mod1 ,并查找:

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

The complexity comes from allowing modules to be directories and also files, instead of forcing each module to be its own directory (maybe trying to avoid the Java folder structure) which would have removed the ambiguity.复杂性来自允许模块是目录和文件,而不是强制每个模块是它自己的目录(可能试图避免 Java 文件夹结构),这将消除歧义。

The key thing to remember is that lib.rs and mod.rs are special files that behave differently to other files in a directory.要记住的关键lib.rsmod.rs特殊文件,它们的行为与目录中的其他文件不同。

They will always be in the module described by the parent folder path (eg src/foo/bar/mod.rs = foo::bar ) while all other files belong to their own modules ( src/foo/bar/baz.rs = foo::bar::baz ).它们将始终位于父文件夹路径所描述的模块中(例如src/foo/bar/mod.rs = foo::bar ),而所有其他文件属于它们自己的模块( src/foo/bar/baz.rs = foo::bar::baz )。

The Rustonic Way乡村方式

Rust has some opinions on this. Rust 对此有一些看法。

Using mod.rs is not recommended anymore, which is good because it has this special behavior from its siblings.不再推荐使用mod.rs ,这很好,因为它具有来自其兄弟姐妹的这种特殊行为。 But lib.rs and main.rs are still special.但是lib.rsmain.rs仍然很特别。

If you want to put tests alongside your code ( foo.rs + foo_test.rs ), it's recommended you don't.如果您想将测试与代码( foo.rs + foo_test.rs )放在一起,建议您不要。 I don't like this, so I use the path thing above, which I think is fine for tests because they are not exported anywhere.我不喜欢这样,所以我使用了上面的path ,我认为这对测试来说很好,因为它们没有被导出到任何地方。 Having to declare tests in the module above feels wrong, and I don't like having to use foo/test.rs either.必须在上面的模块中声明测试感觉是错误的,我也不喜欢必须使用foo/test.rs

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

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