简介
在 Rust 中包含了 Package、Crate、Module 三层:
Package
通过 Cargo 创建的工程就是一个包,目录下包含了一个Cargo.toml
文件。Crate
树状结构保存,用来编译二进制文件,包括了可执行文件、库等。Module
类似于 Java 中的类,采用层级结果,同样对应文件系统目录层级,通过 :: 分割。
模块分成了公开和私有两种控制,使用通过 use
引用,标准库可以参考 Crate std 中的内容。
示例
其中 Cargo.toml
配置文件如下。
[package]
name = "foobar"
version = "0.1.0"
edition = "2021"
[dependencies]
random = "0.14.0"
修改 src/main.rs
文件如下。
fn main() {
println!("Got random {}", rand::random());
}
这里的 rand
可以全局直接使用,无需通过 use
方式引入,不过可以通过 use rand::random;
方式引入到主模块,后续直接使用 random()
函数即可。
简单来说,use
的唯一目的是将符号带入命名空间,让符号使用更加简短。
目录结构
包可以最多包含一个库 crate
以及任意多个二进制 crate
,默认分别将 src/lib.rs
和 src/main.rs
作为 crate
的根,其它二进制包的根放在 src/bin
目录下,而且允许使用目录。如果要使用多个库,可以使用 Workspace
进行管理。
在使用时,可以通过 crate
super
引用。
project/
|-Cargo.toml
`-src/ crate
|-main.rs |
|-config.rs |-config
|-pages/ |-pages
| |-hello.rs | |-hello
| `-login.rs | `-login
|-pages.rs |-pages
|-routes/ |-routes
| |-mod.rs | |
| |-health.rs | |-health
| `-user.rs | `-user
`-models/ |-models
|-mod.rs |
`-user.rs `-user
在 pages.rs
中,可以通过如下方式直接引用,然后就可以使用其内部的实现了。
mod hello;
mod login;
use hello::*;
use login::*;
模块
类似于 C++ 中的 namespace
,通过 mod
声明,默认所有的函数、结构体、枚举、常量等都是私有的,可以通过 pub
将其变为公有。子模块可以通过 super
访问父模块中的所有代码,包括私有代码,而反之不可以。
模块可以放在同一文件、同一目录下,如上,在 main.rs
中可以通过 mod config
方式引用。另外,对于底层目录,可以通过 mod.rs
配置。
同文件
最外层模块不需要设置为 pub 就可以访问,但是内部的实现就需要指定访问权限。
use crate::foo::hi; // 调用路径简化
mod foo {
pub fn hello() {
println!("Hello World!");
}
fn secret() {
println!("Hi world!");
}
pub mod hi {
pub fn say() {
super::secret(); // 可以调用父模块的私有函数
}
}
}
fn main() {
foo::hello(); // 相对路径
crate::foo::hello(); // 绝对路径
foo::hi::say();
hi::say();
}
也可以在模块内通过 pub use
的方式重新导出,如果限制当前 crate
使用,那么就可以配置为 pub(crate)
即可。
常用技巧
依赖库
通常在 src/lib.rs
中引用不同的包,例如上述目录结构中可以使用如下方式。
pub mod errors;
pub use client::Client;
多个二进制
编译过程中会默认查找 src/lib.rs
和 src/main.rs
文件进行编译,默认将 src/bin
目录下的 xxx.rs
文件编译成 xxx
二进制,如果是其它目录,也可以在 Cargo.toml
中通过如下方式指定。
[[bin]]
name ="daemon"
path ="src/daemon/bin/main.rs"
[[bin]]
name ="client"
path ="src/client/bin/main.rs"