module - 当有 main.rs 和 lib.rs 时 Rust 模块混淆

标签 module rust

我有 4 个文件:

main.rs

mod bar;

fn main() {
    let v = vec![1, 2, 3];
    println!("Hello, world!");
}

lib.rs

pub mod foo;
pub mod bar;

foo.rs

pub fn say_foo() {

}

bar.rs

use crate::foo;

fn bar() {
    foo::say_foo();
}

当我运行 cargo run 时,我收到一条错误消息:

error[E0432]: unresolved import `crate::foo`
 --> src/bar.rs:1:5
  |
1 | use crate::foo;
  |     ^^^^^^^^^^ no `foo` in the root

有人可以向我解释如何解决这个问题吗?更广泛地说:当存在 main.rslib.rs 时,模块查找如何工作?

编辑:将 mod foo 添加到 main.rs 修复了这个问题。但我不明白这一点——我的印象是 lib.rs 是“公开”我所有模块的地方?为什么我还必须在 main.rs 中声明模块?

我的 Cargo.toml:

[package]
name = "hello-world"
version = "0.1.0"
authors = ["me@mgail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

最佳答案

让我们从头开始。看Package Layout章节 The Cargo Book .如您所见,您的包裹可能包含很多东西:

  • 一个二进制文件(你可以运行的东西)或多个二进制文件,
  • 单个库(共享代码),
  • 示例,
  • 基准,
  • 集成测试。

包布局

此处并未列出所有可能性,仅列出了二进制文件/库组合。

二进制文件

这是一个包含单个二进制文件的包示例。入口点是 src/main.rs 中的 main 函数。

Cargo.toml:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

src/main.rs:

fn main() {
    println!("Hallo, Rust here!")
}
$ cargo run
Hallo, Rust here!

图书馆

这是一个包含库的包示例。图书馆没有入口点,你不能运行它们。它们用于功能共享。

Cargo.toml:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

src/lib.rs:

pub fn foo() {
    println!("Hallo, Rust library here!")
}
$ cargo run
error: a bin target must be available for `cargo run`

您在 Cargo.toml 文件中看到任何关于二进制文件或库的信息吗?不,原因是我关注了Package Layout cargo 知道去哪里找东西。

一个二进制文件和一个库

这是一个包含二进制文件和库的包示例。

Cargo.toml:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

src/lib.rs:

pub const GREETING: &'static str = "Hallo, Rust library here!";

src/main.rs:

use hallo::GREETING;

fn main() {
    println!("{}", GREETING);
}

同样的问题,您在 Cargo.toml 文件中看到任何关于二进制文件或库的信息吗?没有。

这个包包含两个东西:

  • 二进制文件(根src/main.rs,入口点src/main.rs::main),
  • 一个库(root src/lib.rs,共享代码)。

可以通过 use hallo::... 从二进制文件中引用一个库,其中 hallo 是这个包名(Cargo.toml -> [package] -> name).

你的问题

Cargo.toml:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

相同的包布局

库部分

src/lib.rs:

pub mod bar;
pub mod foo;

src/foo.rs:

pub fn say_foo() {
    println!("Foo");
}

src/bar.rs:

use crate::foo;

pub fn bar() {
    foo::say_foo();
}

crate 指的是 src/lib.rs,因为这里是我们库的上下文。

将其视为一个独立的单元,并通过 use hallo::...; 从外部世界引用它。

二进制部分

src/main.rs:

use hallo::bar::bar;

fn main() {
    bar();
}

这里我们只使用我们的库。

没有图书馆

相同的代码,但是 lib.rs 被重命名为 utils.rs 并且 (foo|bar).rs 文件被移动到src/utils/ 文件夹。

src/utils.rs:

pub mod bar;
pub mod foo;

src/utils/foo.rs:

pub fn say_foo() {
    println!("Foo");
}

src/utils/bar.rs:

use super::foo;
// or use crate::utils::foo;

pub fn bar() {
    foo::say_foo();
}

我们也可以在这里使用 crate,但是因为我们在二进制文件的上下文中,所以路径不同。

src/main.rs:

use utils::bar::bar;

mod utils;

fn main() {
    bar();
}

这里我们刚刚声明了另一个模块 (utils),我们正在使用它。

总结

Cargo.toml 内容:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

如果有一个 src/main.rs 文件,你基本上是这样说的:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[[bin]]
name = "hallo"
src = "src/main.rs"

如果有一个 src/lib.rs 文件,你基本上是这样说的:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[lib]
name = "hallo"
path = "src/lib.rs"

如果两者都有,你基本上是这样说的:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[[bin]]
name = "hallo"
path = "src/main.rs"

[lib]
name = "hallo"
path = "src/lib.rs"

文档

关于module - 当有 main.rs 和 lib.rs 时 Rust 模块混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57756927/

相关文章:

Android Studio 未在项目结构中显示模块

python - rust 中 ndarray::Array1<f64> 中的元素比较

rust - 从行迭代器创建单词迭代器

rust - 为什么通过 DerefMut 可变借用闭包不起作用?

xcode - 将 Swift 应用程序的组件划分为 Swift 模块

python - 将系统 python 安装的 sys.path 附加到我的个人 python 安装中

vba - For 循环案例选择错误

go module @latest 找到但不包含包

rust - 在生成的线程中读取不可变值

Rust 中的静态结构