使用相互引用的结构在单个文件中很常见,但是当我将结构分成两个文件时,我收到错误.
mod_1.rs
mod mod_2;
use mod_2::Haha;
pub struct Hehe {
obj: Haha,
}
fn main() {
Hehe(Haha);
}
Run Code Online (Sandbox Code Playgroud)
mod_2.rs
mod mod_1;
use mod_1::Hehe;
pub struct Haha {
obj: Hehe,
}
fn main() {
Haha(Hehe);
}
Run Code Online (Sandbox Code Playgroud)
这将产生错误.编译时mod_1.rs:
error: cannot declare a new module at this location
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
|
note: maybe move this module `mod_2` to its own directory via `mod_2/mod.rs`
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
note: ... or maybe `use` the module `mod_1` instead of possibly redeclaring it
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
Run Code Online (Sandbox Code Playgroud)
编译时mod_2.rs:
error: cannot declare a new module at this location
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
|
note: maybe move this module `mod_1` to its own directory via `mod_1/mod.rs`
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
Run Code Online (Sandbox Code Playgroud)
在mod_1.rs我使用的东西从mod_2.rs在mod_2.rs,我用mod_1.rs的东西,所以我想找到一种方法来摆脱周期参考模块的问题.
试图让Rust加载文件是一个类似但不同的问题.
这是对Rust模块系统的常见误解.基本上,有两个步骤:
您必须构建模块树.这意味着此模块树中没有循环,并且节点之间存在明确的父子关系.这一步只是告诉Rust要加载哪些文件,与不同模块中某些符号的使用无关.
您现在可以通过其路径(每个模块,最终符号名被分离出的基准在你的模块树中的每个符号::,例如std::io::read).为了避免每次都写入完整路径,您可以使用use声明通过简单名称引用特定符号.
您可以在Rust书籍章节中阅读更多内容.
再次,为了避免混淆:为了使用符号从一个模块,你并不一定要写出mod my_module;你的模块!对于项目中的每个非根模块只有一个在整个项目线说mod said_module;(根模块没有在所有这样的线).只有一次!
关于你的例子:你首先编译mod_1.rs通过rustc mod_1.rs.这意味着这mod_1是您案例中的根模块.如上所述,根模块根本不需要通过声明mod,但是所有其他模块只需要声明一次.这意味着mod mod_2;中mod_1.rs是完全正确的,但是mod mod_1;在mod_2.rs不正确.编译器甚至建议做正确的事情:
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
Run Code Online (Sandbox Code Playgroud)
您已经在使用use它,因此您可以删除该行mod mod_1;并解决此错误.
但是,我认为你仍然在思考模块系统.如上所述,您首先需要设计一个或多或少固定的模块树,这意味着您有一个固定的根模块.无论你传递给什么rustc是根模块,使用不同的模块作为根模块是没有意义的.在您的项目中应该有一个固定的根模块.这可以mod_1如上所述.但是,lib为图书馆和main可执行文件调用它通常更为惯用.
再说一次:首先,在一张纸上绘制模块树.暂时考虑这个问题,然后你可以mod适当地创建文件和声明.
最后一点:即使在修复模块系统时,您的示例也不起作用,因为Haha并且Hehe是具有无限大小的类型.结构的字段直接放入结构的内存布局中(不像Java那样装箱!).因此,除了手动添加间接层(如装箱字段)之外,您不能在结构定义中使用循环.请阅读有关此问题的优秀解释.