使用包、Crate 和模块管理不断增长的项目

随着你编写大型程序,组织代码将变得越来越重要。通过将相关功能分组并将具有不同特性的代码分开,你将明确在哪里可以找到实现特定功能的代码,以及在哪里可以更改功能的工作方式。

到目前为止,我们编写的程序都位于一个文件中的一个模块中。随着项目的增长,你应该通过将代码拆分为多个模块,然后拆分为多个文件来组织代码。一个包可以包含多个二进制 crate 和一个可选的库 crate。随着包的增长,你可以将部分内容提取到单独的 crate 中,这些 crate 成为外部依赖项。本章将涵盖所有这些技术。对于由一组相互关联的包组成的大型项目,Cargo 提供了 工作空间,我们将在第 14 章的 “Cargo 工作空间” 中介绍。

我们还将讨论封装实现细节,这使你可以更高级别地重用代码:一旦你实现了一个操作,其他代码可以通过其公共接口调用你的代码,而无需了解实现的工作原理。你编写代码的方式定义了哪些部分是对其他代码公开的,哪些部分是保留更改权利的私有实现细节。这是另一种限制你需要记住的细节数量的方法。

一个相关的概念是作用域:代码编写的嵌套上下文有一组被定义为“在作用域内”的名称。在阅读、编写和编译代码时,程序员和编译器需要知道特定位置的特定名称是指变量、函数、结构体、枚举、模块、常量还是其他项,以及该项的含义。你可以创建作用域并更改哪些名称在作用域内或外。你不能在同一个作用域内有两个同名的项;有工具可以解决名称冲突。

Rust 有许多功能可以让你管理代码的组织方式,包括哪些细节是公开的,哪些细节是私有的,以及程序中每个作用域内的名称。这些功能有时统称为 模块系统,包括:

  • 包(Packages): Cargo 的一个功能,允许你构建、测试和共享 crate
  • Crate: 生成库或可执行文件的模块树
  • 模块(Modules)use: 让你控制路径的组织、作用域和隐私
  • 路径(Paths): 命名项(如结构体、函数或模块)的方式

在本章中,我们将涵盖所有这些功能,讨论它们如何相互作用,并解释如何使用它们来管理作用域。到最后,你应该对模块系统有扎实的理解,并能够像专业人士一样处理作用域!