| 
						
						
						
					 | 
					 | 
					@ -1,24 +1,24 @@
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					# 包和Package
 | 
					 | 
					 | 
					 | 
					# 包和 Package
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					当读者按照章节顺序读到本章时,意味着你已经几乎具备了参与真实项目开发的能力。但是真实项目远比我们之前的 `cargo new` 的默认目录结构要复杂,好在,Rust 为我们提供了强大的包管理工具:
 | 
					 | 
					 | 
					 | 
					当读者按照章节顺序读到本章时,意味着你已经几乎具备了参与真实项目开发的能力。但是真实项目远比我们之前的 `cargo new` 的默认目录结构要复杂,好在,Rust 为我们提供了强大的包管理工具:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- **Package**:可以用来构建、测试和分享包
 | 
					 | 
					 | 
					 | 
					- **项目(Package)**:可以用来构建、测试和分享包
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- **工作空间workspace**:对于大型项目,可以进一步将多个包联合在一起,组织成工作空间
 | 
					 | 
					 | 
					 | 
					- **工作空间(WorkSpace)**:对于大型项目,可以进一步将多个包联合在一起,组织成工作空间
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- **包Crate**:一个由多个模块组成的树形结构,可以作为三方库进行分发,也可以生成可执行文件进行运行
 | 
					 | 
					 | 
					 | 
					- **包(Crate)**:一个由多个模块组成的树形结构,可以作为三方库进行分发,也可以生成可执行文件进行运行
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- **模块Module**:可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
 | 
					 | 
					 | 
					 | 
					- **模块(Module)**:可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					## 定义
 | 
					 | 
					 | 
					 | 
					## 定义
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					其实 `Package` 和包 `crate` 很容易被搞混,甚至在很多书中,这两者都是不分的,但是由于官方对此做了明确的区分,因此我们会在本章节中试图(挣扎着)理清这个概念。
 | 
					 | 
					 | 
					 | 
					其实项目 `Package` 和包 `Crate` 很容易被搞混,甚至在很多书中,这两者都是不分的,但是由于官方对此做了明确的区分,因此我们会在本章节中试图(挣扎着)理清这个概念。
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#### 包 crate
 | 
					 | 
					 | 
					 | 
					#### 包 Crate
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					对于Rust 而言,包是一个独立的可编译单元,它编译后会生成一个可执行文件或者一个库。
 | 
					 | 
					 | 
					 | 
					对于 Rust 而言,包是一个独立的可编译单元,它编译后会生成一个可执行文件或者一个库。
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					一个包会将相关联的功能打包在一起,使得该功能可以很方便的在多个项目中分享。例如标准库中没有提供但是在三方库中提供的 `rand` 包,它提供了随机数生成的功能,我们只需要将该包通过 `use rand;` 引入到当前项目的作用域中,就可以在项目中使用 `rand` 的功能:`rand::XXX`。
 | 
					 | 
					 | 
					 | 
					一个包会将相关联的功能打包在一起,使得该功能可以很方便的在多个项目中分享。例如标准库中没有提供但是在三方库中提供的 `rand` 包,它提供了随机数生成的功能,我们只需要将该包通过 `use rand;` 引入到当前项目的作用域中,就可以在项目中使用 `rand` 的功能:`rand::XXX`。
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					同一个包中不能有同名的类型,但是在不同包中就可以。例如,虽然 `rand` 包中,有一个 `Rng` 特征,可是我们依然可以在自己的项目中定义一个 `Rng`,前者通过 `rand::Rng` 访问,后者通过 `Rng` 访问,对于编译器而言,这两者的边界非常清晰,不会存在引用歧义。
 | 
					 | 
					 | 
					 | 
					同一个包中不能有同名的类型,但是在不同包中就可以。例如,虽然 `rand` 包中,有一个 `Rng` 特征,可是我们依然可以在自己的项目中定义一个 `Rng`,前者通过 `rand::Rng` 访问,后者通过 `Rng` 访问,对于编译器而言,这两者的边界非常清晰,不会存在引用歧义。
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					## Package
 | 
					 | 
					 | 
					 | 
					## 项目 Package
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					鉴于 Rust 团队标新立异的起名传统,以及包的名称被 `crate` 占用,库的名称被 `library` 占用,因此导致我不知道该如何准确的翻译 `Package`,遂决定,不翻译,但是大家可以把它理解为一个项目工程,或者一个微服务工程。
 | 
					 | 
					 | 
					 | 
					鉴于 Rust 团队标新立异的起名传统,以及包的名称被 `crate` 占用,库的名称被 `library` 占用,经过斟酌, 我们决定将 `Package` 翻译成项目,你也可以理解为工程、软件包。
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					由于 `Package` 就是一个项目,因此它包含有独立的 `Cargo.toml` 文件,以及因为功能性被组织在一起的一个或多个包。一个 `Package` 只能包含**一个**库(library)类型的包,但是可以包含**多个**二进制可执行类型的包。
 | 
					 | 
					 | 
					 | 
					由于 `Package` 就是一个项目,因此它包含有独立的 `Cargo.toml` 文件,以及因为功能性被组织在一起的一个或多个包。一个 `Package` 只能包含**一个**库(library)类型的包,但是可以包含**多个**二进制可执行类型的包。
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -34,12 +34,12 @@ $ ls my-project/src
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					main.rs
 | 
					 | 
					 | 
					 | 
					main.rs
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					```
 | 
					 | 
					 | 
					 | 
					```
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					这里,Cargo 为我们创建了一个名称是 `my-project` 的 `Package`,同时在其中创建了 `Cargo.toml` 文件,可以看一下该文件,里面并没有提到 `src/main.rs` 作为程序的入口,原因是 Cargo 有一个惯例:**src/main.rs是二进制包的根文件,该二进制包的包名跟所属package相同,在这里都是my-project**,所有的代码执行都从该文件中的 `fn main()` 函数开始。
 | 
					 | 
					 | 
					 | 
					这里,Cargo 为我们创建了一个名称是 `my-project` 的 `Package`,同时在其中创建了 `Cargo.toml` 文件,可以看一下该文件,里面并没有提到 `src/main.rs` 作为程序的入口,原因是 Cargo 有一个惯例:**`src/main.rs` 是二进制包的根文件,该二进制包的包名跟所属 `Package` 相同,在这里都是 `my-project`**,所有的代码执行都从该文件中的 `fn main()` 函数开始。
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					使用 `cargo run` 可以运行该项目,输出:`Hello, world!`。
 | 
					 | 
					 | 
					 | 
					使用 `cargo run` 可以运行该项目,输出:`Hello, world!`。
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#### 库 Package
 | 
					 | 
					 | 
					 | 
					#### 库 Package
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					再来创建一个库类型的 `package`:
 | 
					 | 
					 | 
					 | 
					再来创建一个库类型的 `Package`:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					```console
 | 
					 | 
					 | 
					 | 
					```console
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					$ cargo new my-lib --lib
 | 
					 | 
					 | 
					 | 
					$ cargo new my-lib --lib
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					     Created library `my-lib` package
 | 
					 | 
					 | 
					 | 
					     Created library `my-lib` package
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -66,7 +66,7 @@ error: a bin target must be available for `cargo run`
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#### 典型的 `Package` 结构
 | 
					 | 
					 | 
					 | 
					#### 典型的 `Package` 结构
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					上面创建的 `Package` 中仅包含 `src/main.rs` 文件,意味着它仅包含一个二进制同名包 `my-project`。如果一个 `Package` 同时拥有 `src/main.rs` 和 `src/lib.rs`,那就意味着它包含两个包:库包和二进制包,这两个包名也都是 `my-project` —— 都与 `package` 同名。
 | 
					 | 
					 | 
					 | 
					上面创建的 `Package` 中仅包含 `src/main.rs` 文件,意味着它仅包含一个二进制同名包 `my-project`。如果一个 `Package` 同时拥有 `src/main.rs` 和 `src/lib.rs`,那就意味着它包含两个包:库包和二进制包,这两个包名也都是 `my-project` —— 都与 `Package` 同名。
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					一个真实项目中典型的 `Package`,会包含多个二进制包,这些包文件被放在 `src/bin` 目录下,每一个文件都是独立的二进制包,同时也会包含一个库包,该包只能存在一个 `src/lib.rs`:
 | 
					 | 
					 | 
					 | 
					一个真实项目中典型的 `Package`,会包含多个二进制包,这些包文件被放在 `src/bin` 目录下,每一个文件都是独立的二进制包,同时也会包含一个库包,该包只能存在一个 `src/lib.rs`:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					```css
 | 
					 | 
					 | 
					 | 
					```css
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -88,7 +88,7 @@ error: a bin target must be available for `cargo run`
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					```
 | 
					 | 
					 | 
					 | 
					```
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- 唯一库包:`src/lib.rs`
 | 
					 | 
					 | 
					 | 
					- 唯一库包:`src/lib.rs`
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- 默认二进制包:`src/main.rs`,编译后生成的可执行文件与`package`同名
 | 
					 | 
					 | 
					 | 
					- 默认二进制包:`src/main.rs`,编译后生成的可执行文件与 `Package` 同名
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- 其余二进制包:`src/bin/main1.rs` 和 `src/bin/main2.rs`,它们会分别生成一个文件同名的二进制可执行文件
 | 
					 | 
					 | 
					 | 
					- 其余二进制包:`src/bin/main1.rs` 和 `src/bin/main2.rs`,它们会分别生成一个文件同名的二进制可执行文件
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- 集成测试文件:`tests` 目录下
 | 
					 | 
					 | 
					 | 
					- 集成测试文件:`tests` 目录下
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					- 基准性能测试 `benchmark` 文件:`benches` 目录下
 | 
					 | 
					 | 
					 | 
					- 基准性能测试 `benchmark` 文件:`benches` 目录下
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |