rust 入门-模块系统
不太一样的模块系统
相信 rust 的初学者都会有这样一个疑问:我要怎么引入其他文件/文件夹下写好的函数变量等?。不同于 python 或者 java 这样通过文件路径来确定模块路径的语言,rust 有一套自己的模块系统。该模块系统的层级关系不一定就是文件的层级关系。
初探 mod
在 rust 中通过 mod 来定义一个模块,例如:
pub mod say {
pub fn say_hello(){
println!("hello");
}
}
并且,如果我将其和 main 放在同一个目录:
├── src
│ ├── hello.rs
│ └── main.rs
那么此时我们应该通过以下方式引用 say_hello:
mod hello;
fn main() {
hello::say::say_hello();
}
第一行 mod hello; 表示声明一个模块,rust 会认为以下文件路径为模块内容:
- hello.rs
- hello/mod.rs
而我们在 hello.rs 中又声明了新的模块 say,并且声明和定义在同一个地方。因此可以使用 hello::say::say_hello() 来访问, 还可以使用 use 语句:
mod hello;
use hello::say;
fn main() {
say::say_hello();
}
可以看出,在 rust 中使用一个非第三方模块必须先使用 mod 声明,而不能直接使用 use。
假设我们修改文件层级关系,将 say_hello 放入 src/hello/say.rs 中:
├── src
│ ├── hello
│ │ └── say.rs
│ └── main.rs
我们是否能使用 mod hello.say 来声明模块呢?答案是不能。我们必须在 hello 中建立 mod.rs 然后在 mod.rs 中声明。此时 3 个文件内容为:
// src/hello/say.rs
pub fn say_hello(){
println!("hello");
}
// src/hello/mod.rs
pub mod say; // 声明 mod say
// src/main
mod hello;
fn main() {
hello::say::say_hello();
}
此外,还有一种方法,我们可以声明与 hello 文件夹同名的 hello.rs,在 hello.rs 中可以访问 hello 文件夹下的代码文件:
├── src
│ ├── hello
│ │ └── say.rs
│ └── hello.rs
│ └── main.rs
此时代码为:
// src/hello/say.rs
pub fn say_hello(){
println!("hello");
}
// src/hello.rs
pub mod say; // 声明 mod say
// src/main
mod hello;
fn main() {
hello::say::say_hello();
}
这种方式不用在 hello 下建立一个 mod.rs。
默认权限
在 rust 中默认权限都是外部不可访问,例如在 hello.rs 中定义一个 struct 然后在 main 中进行实例化,编译器会提示异常:
struct People{
name: String
}
fn main() {
let p = hello::People{
name: String::from("dd")
};
}
let p = hello::People{
| ^^^^^^ private struct
试图给 People 定义添加 pub:
pub struct People{
name: String
}
fn main() {
let p = hello::People{
name: String::from("dd")
};
}
|
4 | name: String::from("dd")
| ^^^^^^^^^^^^^^^^^^^^^^^^ private field
又会收到新的异常,提示 name 这个字段是私有的。因此我们还需要:
pub mod say;
pub struct People{
pub name: String
}
可以看出,rust 对权限管控非常严格,从 field 级别开始,如果不申明为 pub 外部一律无法访问。
总结
在 rust 中,模块有以下特点:
- 使用非第三方模块必须先使用 mod 进行定义后使用,不像其他语言可以直接 import。
- 声明语句
mod xxx;表示从xxx.rs 或 xxx/mod.rs中寻找内容。 - 定义时默认为 private,如果要暴露给其他文件使用,必须显式声明为
pub。