Rust模块的使用
2024-03-17 17:33:41

模块定义

模块分为两种形式存在

内联模块

内敛模块就是写在源文件内部

1
2
3
4
5
6
7
8
9
mod mod1 {
pub fn add(n: i32) -> i32 {
n + 5
}
}

fn main() {
println!("{}", mod1::add(5));
}

虽然是在同一个文件,但也要求函数用pub关键字公开才能访问。

文件模块

默认情况下,文件模块以两种形式存在

  1. module_name.rs
    此时文件名就是模块名。
  2. module_name/mod.rs
    此时文件夹名就是模块名。

如果同时存在同名文件和文件夹会如何呢?这会产生歧义,编译器会发出错误

1
error[E0761]: file for module `mod2` found at both "src\mod2.rs" and "src\mod2\mod.rs"

并要求删除其中一个

1
help: delete or rename one of them to remove the ambiguity

用文件夹的方式是为了用嵌套模块,子模块文件应该在文件夹下,比如parent/child.rs,然后在mod.rs文件中导出子模块

1
pub mod child;

不过需要注意,这个mod.rs的约定从 Rust 2018 开始就不推荐了,因为当模块过多时将会有很多同名文件。

包含子模块的模块

从 Rust 2018 起,就不要再用mod.rs那样的方式组织子模块了,推荐方式是这样

1
2
3
4
main.rs
foo.rs
foo/bar.rs
foo/bar/xyz.rs

这样就有3个层级

1
2
3
4
5
6
7
mod foo;

fn main() {
println!("{}", foo::add(5));
println!("{}", foo::bar::add(5));
println!("{}", foo::bar::xyz::add(5));
}

模块引用方式

默认方式

mod module_name引用即可

1
2
3
4
5
mod mod2;

fn main() {
println!("{}", mod2::add(5));
}

path属性定位模块文件

假设有一个模块文件在src/a/b/c.rs文件中,那么使用时可以通过path属性定位,并且模块名可以自定义

1
2
3
4
5
6
#[path = "a/b/c.rs"]
mod mod3;

fn main() {
println!("{}", mod3::add(5));
}

include宏包含模块

1
2
3
4
5
6
7
mod mod3 {
include!("a/b/c.rs");
}

fn main() {
println!("{}", mod3::add(5));
}

这样也可以自定义模块名。主要的区别是include!会把代码文件插入进来,这可以用于将大量的代码拆分到多个文件中,使代码更加清晰和易于维护。
但这样做的缺点是对IDE提示不友好,无法得知模块内提供了什么内容。

模块访问权限

默认情况下,模块内所有数据都是私有的,需要通过pub关键字公开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 将子模块公开
pub mod bar;

// 公开。可以从任何地方访问
pub fn add1(n: i32) -> i32 {
n + 50
}

// 私有。本模块和子模块可访问
pub(self) fn add2(n: i32) -> i32 {
n + 50
}

// 内部。就是在当前工程内均可见
pub(crate) fn add3(n: i32) -> i32 {
n + 50
}

// 父模块可见
pub(super) fn add4(n: i32) -> i32 {
n + 50
}

// 指定的模块可见
pub(in crate::other) fn add5(n: i32) -> i32 {
n + 50
}