ChatGPT解决这个技术问题 Extra ChatGPT

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

按照 this guide,我创建了一个 Cargo 项目。

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

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


S
Shepmaster

您不需要 hello.rs 文件中的 mod hello。除 crate 根目录(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!");
}

如果我用 use hello 而不是 mod hello 指定它,那么迟到的问题是否也有效?!
@ChristianSchmitt 不,它们是不同的东西。 use 只是一个命名空间的东西,而 mod 拉入文件。例如,您可以使用 use 来调用 print_hello 函数,而无需使用命名空间作为前缀
S
Shepmaster

如果您希望有嵌套模块...

生锈 2018

拥有文件 mod.rsno longer required(尽管它仍然受支持)。惯用的替代方法是将文件命名为模块的名称:

$ 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 by Example 更好地解释了它。

$ 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()`");
}

假设我想在 nested.rs 中使用来自 inaccessible.rs 的东西...我该怎么做?
要从 main.rs 以外的文件访问同级 .rs 文件,请使用 path 属性。因此,在nested.rs 的顶部,添加以下内容:#[path = "inaccessible.rs"] 和下一行:mod inaccessible;
@甘地见The path attribute
@HemanGandhi 将 mod inaccessible; 添加到 my/mod.rs 以使其成为 my 的子模块,然后通过相对路径 super::inaccessible::function()nested.rs 访问兄弟模块。您在这里不需要 path 属性。
我不确定 2018 年在目录之后命名文件的方式是否更惯用。对于一个干净的目录树,我更喜欢旧方法,并且大量的 crate 也遵循它。
P
Peter Mortensen

我真的很喜欢Gardener's response。我一直在为我的模块声明使用建议。

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

文件 main.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;
作为一个 Rust 新手,这么简单的概念(导入其他代码)需要这么多研究,这有点令人不安。加上 #[path..] 语法很难看
这是误导性的,除非在晦涩难懂的情况下,否则不应使用 #[path = ...] 属性,当然新手也不应使用。每次执行 mod thing,它创建一个新模块,即使 #[path = ...] 使它们指向同一个文件。这意味着在此示例中,声明了两个单独的 thing 模块:crate::thingcrate::other_thing::thing。它在这里可能不是问题,因为它只包含一个函数,但是如果您定义类型,当编译器报告“预期的 mod1::A,找到 mod2::A”时,它可能会导致混淆。
请使用标准机制。如果您确实想要这种没有中间 mod.rs 文件的文件结构,您可以在 main.rs 中声明它们,如 mod other_utils { pub mod other_thing; }mod utils { pub mod thing; }。然后您可以像 crate::other_utils::other_thingcrate::utils::thing 一样访问它们。
P
Peter Mortensen

在非 main.rs(或 lib.rs)文件中,如果您想从同一目录中的文件中包含,则下面的代码有效。关键是使用单词 super:: 表示包含。 (这就是我在不使用 path 的情况下重写 answer of rodo 的方式。)

目录树:

src
├── main.rs
├── my.rs
└── my
    ├── a.rs
    └── b.rs

要在 b.rs 中包含 a.rs:

文件 src/my/a.rs

pub fn function() {
    println!("src/my/a.rs/function()");
}

文件 src/my/b.rs

use super::b::function;

fn f2() {
    function();
}

文件 src/my.rs

mod a;
mod b;

文件 src/main.rs

mod my;

P
Peter Mortensen

截至 2022 年

├── src
├── main.rs
├── scripts
│   └── func.rs
└── scripts.rs

如果我想从 func.rs 文件(位于 scripts 文件夹内)调用函数,我在根目录中创建了一个与文件夹名称相同的所谓“链接”文件(不必有链接文件名和文件夹名相同)。

文件脚本/func.rs 的内容:

pub fn sayHello(){
    println!("Hello, World!");
}

在 scripts.rs 文件中,我有:

pub(crate) mod func;

然后在我的 main.rs 文件中,我调用了 sayHello() 函数,如下所示:

mod scripts;
fn main() {
    scripts::func::sayHello();
}

关于“截至 2022 年”:您能state提供东西的版本(编译器、约定、文档/规范等)吗?也许还有在哪个系统(包括版本)上进行了测试。 (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
G
Gabriel soft

这是解决此问题的一种失败的简单方法,您需要将 mod 添加到 main.rs 文件中,以便在整个文件树中都可以访问它


没有例子,没有提到需要从模块文件中删除 mod,这个答案没有添加现有答案没有的任何内容。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅