如何包含来自同一项目中另一个文件的模块?


130

按照本指南,我创建了一个货运项目。

src/main.rs

fn main() {
    hello::print_hello();
}

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

我运行使用

cargo build && cargo run

并且它编译没有错误。现在,我试图将主模块一分为二,但无法弄清楚如何从另一个文件中包含一个模块。

我的项目树看起来像这样

├── src
    ├── hello.rs
    └── main.rs

以及文件的内容:

src/main.rs

use hello;

fn main() {
    hello::print_hello();
}

src/hello.rs

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

当我编译它cargo build,我得到

error[E0432]: unresolved import `hello`
 --> src/main.rs:1:5
  |
1 | use hello;
  |     ^^^^^ no `hello` external crate

我尝试遵循编译器的建议,并修改main.rs为:

#![feature(globs)]

extern crate hello;

use hello::*;

fn main() {
    hello::print_hello();
}

但这仍然无济于事,现在我明白了:

error[E0463]: can't find crate for `hello`
 --> src/main.rs:3:1
  |
3 | extern crate hello;
  | ^^^^^^^^^^^^^^^^^^^ can't find crate

是否有一个简单的示例,说明如何将当前项目中的一个模块包含到项目的主文件中?



Answers:


237

mod hellohello.rs文件中不需要。除板条根(main.rs可执行文件,lib.rs库文件)以外的任何文件中的代码都会自动在模块中命名。

要在其中包含代码hello.rs,请main.rs使用mod hello;。它被扩展到其中的代码hello.rs(与您之前完全一样)。您的文件结构保持不变,并且您的代码需要稍作更改:

main.rs

mod hello;

fn main() {
    hello::print_hello();
}

hello.rs

pub fn print_hello() {
    println!("Hello, world!");
}

1
如果我使用use hello而不是mod hello来指定它,后期问题也不会起作用吗?
Christian Schmitt

16
@ChristianSchmitt不,他们是不同的东西。use只是一个名称空间的东西,而mod拉入文件。use例如,您将使用该print_hello函数而无需使用名称空间作为前缀来调用该函数
Renato Zannon 2015年

25

如果您希望使用嵌套模块...

锈2018

不再需要有文件mod.rs(尽管它仍然支持)。惯用的替代方法是将文件命名为模块名称:

$ tree src
src
├── main.rs
├── my
│   ├── inaccessible.rs
│   └── nested.rs
└── my.rs

main.rs

mod my;

fn main() {
    my::function();
}

my.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}

锈2015

您需要在mod.rs文件夹中放置一个与模块同名的文件。举例来说,Rust解释得更好。

$ tree src
src
├── main.rs
└── my
    ├── inaccessible.rs
    ├── mod.rs
    └── nested.rs

main.rs

mod my;

fn main() {
    my::function();
}

mod.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}

4
假设我想用一些东西inaccessible.rsnested.rs......我怎么会做呢?
Heman Gandhi

要从main.rs以外的文件访问同级.rs文件,请使用path属性。因此,在nested.rs的顶部添加以下内容: #[path = "inaccessible.rs"]并在下一行:mod inaccessible;
Gardener

@Gandhi See the path属性
园丁

2
@HemanGandhi添加mod inaccessible;使其my/mod.rs成为其子模块my,然后nested.rs通过相对路径从同级模块访问super::inaccessible::function()。您path在这里不需要属性。
artin

9

我真的很喜欢园丁的回应。我一直在对模块声明使用建议。如果存在技术问题,请有人提出。

./src
├── main.rs
├── other_utils
│   └── other_thing.rs
└── utils
    └── thing.rs

#[path = "utils/thing.rs"] mod thing;
#[path = "other_utils/other_thing.rs"] mod other_thing;

fn main() {
  thing::foo();
  other_thing::bar();
}

utils / thing.rs

pub fn foo() {
  println!("foo");
}

other_utils / other_thing.rs

#[path = "../utils/thing.rs"] mod thing;

pub fn bar() {
  println!("bar");
  thing::foo();
}

只好用这种“伎俩”,以再出口fn具有相同的名称,因为它是在文件。#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
Arek巴尔

这应该是被接受的答案imo
Homam Bahrani
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.