开发环境
- Windows 10
- Rust 1.60.0
- VS Code 1.67.2
项目工程
这里继续沿用上次工程rust-demo
基础概念
当你编写大型程序时,组织你的代码将是重要的,因为在你的头脑中保持整个程序的轨迹将变得不可能。通过对相关的功能进行分组,并将代码与不同的功能分开,您将清楚在哪里可以找到实现特定功能的代码,以及在哪里可以更改功能的工作方式。
到目前为止,我们编写的程序都在一个文件的一个模块中。随着项目的增长,您可以通过将代码分成多个模块和多个文件来组织代码。一个包可以包含多个二进制板条箱和一个可选的库板条箱。随着包的增长,您可以将部件提取到独立的板条箱中,成为外部依赖项。本章涵盖了所有这些技术。对于由一组相互关联的包组成的非常大的项目,Cargo提供了工作空间。
除了对功能进行分组之外,封装实现细节还可以让您在更高的层次上重用代码:一旦实现了一个操作,其他代码就可以通过代码的公共接口调用该代码,而无需知道实现是如何工作的。您编写代码的方式定义了哪些部分是公共的供其他代码使用,哪些部分是私有的实现细节,您保留更改这些细节的权利。这是限制你必须记住的细节数量的另一种方法。
一个相关的概念是范围:编写代码的嵌套上下文有一组被定义为“在范围内”的名称在读取、编写和编译代码时,程序员和编译器需要知道特定位置的特定名称是否引用了变量、函数、结构、枚举、模块、常量或其他项,以及该项的含义。您可以创建范围并更改范围内或范围外的名称。在同一范围内不能有两个同名的项目;有解决名称冲突的工具。
Rust有许多特性允许你管理你的代码的组织,包括哪些细节是公开的,哪些细节是私有的,以及在你的程序中的每个作用域中有什么名字。这些功能有时统称为module system,包括:
- Package(包):一个Cargo功能,让您建立,测试,和共享箱
- Crates(箱):生成库或可执行文件的模块树
- Modules(模块)和use:让您控制路径的组织、范围和隐私
- Paths(路径):一种命名项目的方式,如结构、函数或模块
Package(包) & Crates(箱)
我们将介绍的模块系统的第一部分是Package和Crates。
Package是提供一组功能的一个或多个Crates。一个Package包含一个Cargo.toml文件,该文件描述了如何构建这些Crates。
Crates可以是二进制的Crates或库Crates。二进制Crates是可以编译成可运行的可执行文件的程序,例如命令行程序或服务器。它们必须有一个名为main的函数来定义可执行文件运行时发生的事情。到目前为止,我们创建的所有Crates都是二进制的Crates。
库Crates没有主函数,也不会编译成可执行文件。它们定义了多个项目共享的功能。例如,我们在前面章节中使用的rand crate提供了生成随机数的功能。
crate root是一个源文件,Rust编译器从它开始,并构成了crate的根模块。
几个规则决定了一个package可以包含什么。一个package最多可以包含一个库crate。它可以包含任意数量的二进制crate,但必须至少包含一个crate(库或二进制文件)。
让我们看一下当我们创建一个package时会发生什么。首先,我们输入命令cargo new:
$ cargo new my-project // 创建工程
Created binary (application) `my-project` package
$ ls my-project // 查看工程
Cargo.toml
src
$ ls my-project/src // 查看目录
main.rs
当我们输入命令时,cargo创建了一个cargo.toml文件,给了我们一个package。查看cargo.toml的内容,没有提到src/main.rs,因为cargo遵循一个约定,src/main.rs是与package同名的二进制crate的crate根。同样,cargo知道如果包目录包含src/lib.rs,那么package包含一个与package同名的库crate,src/lib.rs是它的crate root。cargo将板条箱根文件传递给rustc来构建库或二进制文件。
这里,我们有一个只包含src/main.rs的package,这意味着它只包含一个名为my-project的二进制文件。如果一个package包含src/main.rs和src/lib.rs,那么它有两个crate :一个二进制文件和一个库,两者的名称都与package的名称相同。通过将文件放在src/bin目录中,一个package可以有多个二进制crate :每个文件将是一个单独的二进制crate。
本章重点
- Package(包)的概念
- Crate(箱)的概念