使用包、Crates 和模块管理不断增长的项目
随着你编写大型程序,组织你的代码将变得越来越重要。通过对相关功能进行分组和分离具有不同特性的代码,你将清楚地知道在哪里找到实现特定功能的代码,以及在哪里修改功能的工作方式。
到目前为止,我们编写的程序都在一个文件中的一个模块中。随着项目的增长,你应该通过将代码拆分为多个模块,然后再拆分为多个文件来组织代码。一个包可以包含多个二进制 crate,并且可以选择包含一个库 crate。随着包的增长,你可以将部分内容提取到单独的 crate 中,这些 crate 将成为外部依赖项。本章涵盖了所有这些技术。对于包含一组共同演进的相互关联的包的非常大的项目,Cargo 提供了工作区,我们将在第 14 章的“Cargo 工作区”节中介绍。
我们还将讨论封装实现细节,这使你可以在更高级别重用代码:一旦你实现了某个操作,其他代码就可以通过其公共接口调用你的代码,而无需知道实现的工作原理。你编写代码的方式定义了哪些部分是公共的,供其他代码使用,哪些部分是私有的实现细节,你保留更改的权利。这是限制你必须记在脑海中的细节量的另一种方法。
一个相关的概念是作用域:编写代码的嵌套上下文具有一组定义为“在作用域中”的名称。在读取、编写和编译代码时,程序员和编译器需要知道特定位置的特定名称是指变量、函数、结构体、枚举、模块、常量还是其他项,以及该项的含义。你可以创建作用域并更改哪些名称在作用域内或作用域外。你不能在同一作用域中拥有两个同名的项;有工具可以解决名称冲突。
Rust 有许多功能允许你管理代码的组织,包括哪些细节是公开的,哪些细节是私有的,以及程序中每个作用域中的名称是什么。这些功能有时统称为模块系统,包括
- 包: Cargo 功能,可让你构建、测试和共享 crate
- Crates: 模块树,生成库或可执行文件
- 模块和 use: 让你控制路径的组织、作用域和私有性
- 路径: 一种命名项(例如结构体、函数或模块)的方式
在本章中,我们将介绍所有这些功能,讨论它们如何交互,并解释如何使用它们来管理作用域。到最后,你应该对模块系统有一个扎实的理解,并且能够像专业人士一样处理作用域!