这一部分的中文教程/文档都很混乱,翻译也五花八门,所以我建议直接看英文官方文档,对于一些名词不要进行翻译,翻译只会让事情更混乱,本篇从实战和实际需求出发,讲解几个名称的关系。
Module & Crate & Package & Workspace
英文中的意思:
Cargo:货物
Crate:板条箱,装箱
package:包裹,包装
Module:组件,模块
看原始翻译的原因是通过原生翻译来理解为什么设计者要用这些名字命名。
当你想要写一个简单代码的时候,可以直接写一个main.rs然后编译:
rust
fn main() {
println!("Hello, world!");
}
当业务逻辑接着扩展,出现了很多命名冲突,为了解决这个问题,引入Module,将所有的相关的代码打包成Module,Module是Rust中代码结构的最小组成部分:
rust
mod chinese{
pub fn hello() {
println!("你好,Rust!");
}
}
mod english{
pub fn hello() {
println!("Hello, Rust!");
}
}
fn main() {
println!("Hello, world!");
chinese::hello();
english::hello();
}
当代码量变大的时候,需要将代码分为多个文件存储,然后整体编译成一个文件,这时把这个称为Crate:
rust
//main.rs文件
pub mod chinese;
pub mod english;
fn main() {
chinese::hello();
english::hello();
}
//english.rs文件
pub fn hello() {
println!("Hello, Rust!");
}
//chinese.rs文件
pub fn hello() {
println!("你好, Rust!");
}
其实前面只有一个文件,也可以看作只有一个文件的crate
当代码量更多了,或者跟别人协作了,各自有各自写的crate,这时就需要把多个crate组合成一个package,package就是一个完整的项目,可以包含多个binary crate【也就是,生成可执行文件的crate】和至多一个library crate【也就是只提供功能的crate】,注意,这里的意思是,一个package编译后可以生成多个可执行文件,但是如果要编译成库的话,只能生成一个lib库,并不是指一个package只能包括一个库,使用第三方库数量没有限制的。
例如你写了一个push crate,编译后生成一个可执行文件push,你同事写了一个pull crate,编译后生成一个可执行文件pull,你们就可以组成一个package,编译后生成push和pull两个可执行文件
crate和package的界限没有那么明确,一个main函数就是一个crate,一个或多个crate组合到一起就是package了。
rust
//main.rs
fn main(){
println!("Hello Rust from main.rs!");
}
// src/bin/abc.rs
fn main(){
println!("Hello Rust from abc.rs!");
}
//lib.rs,library crate,会编译成一个libxxx.rlib
pub fn all_usr_can_use(){
println!("all user can use");
}
当代码量更大了,多个工作组各自做的package融合到一起,形成一个workspace,workspace是用于多个package进行联合工作的。在workspace下,多个package会共用一个Cargo.block,在workspace下会有一个Cargo.toml,各个package中也会有自己的Cargo.toml。
其中workspace下的Cargo.toml的内容:
xml
[workspace]
edition = "2021"
resolver = "2"
members=["module_system","package2"]
module
module是Rust项目管理中组织代码架构的最小单元,命名空间一般和module是一起出现的,module可以嵌套,可以写在与module同名的rs文件中,也可以放在与module同名的文件夹中,编译器会在文件夹中查找解析mod.rs文件,如果没有会报错。
Crate
Rust中的独立可编译单元,分为两类,一类是binary crate,编译出来是一个可执行文件;另一类是library crate,编译出来是一个二进制库文件。
binary crate需要有main.rs文件,里面要有main函数,作为程序入口。
library crate需要有lib.rs文件,将要暴露给他人的接口放到这个文件中。
package
多个crate组合形成的一个项目,一个package编译结果可以是多个可执行文件,但是最多只能有一个二进制库,也就是说如果你这个项目要让别人用,那么别人看见你只是一个整体库,不会关心你内部如何划分
workspace
多个package组合形成的大型项目,目前还没用过。
常用库
- 正则表达式:regex
- 日志:log
- 日期:chrono
- HTTP 客户端:reqwest
- 增强错误处理:thiserror、anyhow
- 数据库:rusqlite、r2d2