diff --git a/projects/my-project/Cargo.toml b/projects/my-project/Cargo.toml index aebde11..639adf9 100644 --- a/projects/my-project/Cargo.toml +++ b/projects/my-project/Cargo.toml @@ -1,8 +1,6 @@ [package] name = "my-project" version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +edition = "2024" [dependencies] diff --git a/src/Ch07_Managing_Growing_Projects_with_Packages_Crates_and_Modules.md b/src/Ch07_Managing_Growing_Projects_with_Packages_Crates_and_Modules.md index 1b41835..b0d5501 100644 --- a/src/Ch07_Managing_Growing_Projects_with_Packages_Crates_and_Modules.md +++ b/src/Ch07_Managing_Growing_Projects_with_Packages_Crates_and_Modules.md @@ -4,19 +4,17 @@ 到目前为止,我们已编写的程序都在一个文件的一个模组中。随着项目增长,咱们应通过把代码拆分为多个模组,然后拆分为多个文件来组织代码。一个包可以包含多个二进制代码箱,也可以包含一个库代码箱。随着包的增长,咱们可提取各个部分到单独的代码箱,而成为外部依赖项。这一章介绍所有这些技巧。对于由一组共同发展互相关联的包组成的超大型项目,Cargo 提供了 *工作空间,workspaces*,我们将在第 14 章中的 [Cargo 工作空间](../crates-io/workspace.md) 小节中介绍。 -我们还将讨论封装实现的细节,这让咱们可在更高级别重用代码:一旦咱们实现了某项操作,其他代码可以通过其公共接口调用咱们的代码,而不必了解实现的工作原理。咱们编写代码的方式定义了哪些部分属于公开供其他代码使用的,以及哪些部分属于咱们保留更改权利的私有实现细节。这是限制咱们必须记住细节数量的另一方式。 +我们还将讨论对实现细节进行封装,这让咱们可在更高级别重用代码:一旦咱们实现了某项操作,其他代码可以通过其公共接口调用咱们的代码,而不必了解该实现的工作原理。咱们编写代码的方式,定义了哪些部分属于公开供其他代码使用的,以及哪些部分属于咱们保留更改权利的私有实现细节。这是对咱们必须记住的细节数量有所限制的另一方式。 -一个相关的概念是作用域:代码写下之处的嵌套上下文,都有一组被定义为 “在作用域中” 的名字。在阅读、编写及编译代码时,程序员和编译器都需要知道,某个特定点位上的特定名字,是否引用了某个变量、函数、结构体、枚举、模组、常量,或其他项目及该项目的含义。咱们可以创建出作用域,并改变哪些名字在作用域内或在作用域外。在同一个作用域中,咱们不能有两个同名的项目;有一些可用于解决名字冲突的工具。 - -Rust 有着数项特性,可以让咱们管理咱们代码的组织,包括哪些细节会暴露,哪些细节属于私有的,以及咱们程序中的各个作用域中都有哪些名字。这些特性有时统称为 *模组系统,module system*,包括: +一个相关的概念是作用域:代码写下之处的嵌套上下文,都有一组被定义为 “在作用域中” 的名字。在阅读、编写及编译代码时,程序员和编译器都需要知道,某个特定点位上的某一特定名字,是否引用了某个变量、函数、结构体、枚举、模组、常量,或其他项目及该项目的含义。咱们可以创建作用域,并改变哪些名字在作用域内或在作用域外。在同一个作用域中,咱们不能有两个同名的项目;有一些可用于解决名字冲突的工具。 +Rust 有着数项可以让咱们管理咱们代码的组织的特性,包括哪些细节会暴露,哪些细节属于私有的,以及咱们程序中的各个作用域中都有哪些名字。这些特性有时统称为 *模组系统,module system*,包括: - **包,package**:让咱们构建、测试和共享代码箱的 Cargo 特性; - **代码箱,crate**:产生库或可执行程序的模组树; - **模组,module** 与 **`use` 关键字**:让咱们可以控制路径的组织、作用域及隐私; - **路径,path**:命名项目的一种方式,例如结构体、函数或模组。 - 在这一章中,我们将介绍所有这些特性,讨论他们如何交互,并解释如何使用他们来管理作用域。到本章结束时,咱们应对模组系统有扎实了解,并能像专业人士一样,使用作用域! diff --git a/src/getting_started/hello_world.md b/src/getting_started/hello_world.md index 530e084..1f8b227 100644 --- a/src/getting_started/hello_world.md +++ b/src/getting_started/hello_world.md @@ -7,9 +7,6 @@ ## 创建项目的目录 -**Creating a Project Directory** - - 首先,咱们将创建一个存储咱们 Rust 代码的目录。对于 Rust 来说,代码存放在哪里并不重要,但对于本书中的练习和项目,我们建议在咱们的主目录下,创建一个 `projects` 目录,并将咱们的所有项目,都放在那里。 请打开某个终端,并输入以下命令,创建 `projects` 目录,并在 `projects` 目录下,创建出这个 "Hello, world!" 的项目目录。 @@ -32,7 +29,7 @@ $ cd hello_world > cd hello_world ``` -## 编写并运行一个 Rust 程序 +## Rust 程序基础 接下来,请创建一个新的源文件,并将其命名为 `main.rs`。Rust 文件总是以 `.rs` 扩展名结尾。如果咱们在文件名中,使用了多个单词,惯例是要使用下划线,分隔这些单词。例如,请使用 `hello_world.rs`,而不是 `helloworld.rs`。 diff --git a/src/packages_crates_and_modules/packages_and_crates.md b/src/packages_crates_and_modules/packages_and_crates.md index bc96125..739feaf 100644 --- a/src/packages_crates_and_modules/packages_and_crates.md +++ b/src/packages_crates_and_modules/packages_and_crates.md @@ -1,28 +1,26 @@ -# 包与代码箱 +# 代码包与代码箱 -**Packages and Crates** +我们将介绍的模组系统的前两个部分,分别是代码包与代码箱。 +所谓 *代码箱,crate*,是 Rust 编译器一次考虑的最小代码量。即使咱们运行 `rustc` 而不是 `cargo`,并传递单个源代码文件(正如我们在第 1 章中 [Rust 程序基础](../getting_started/hello_world.md#rust-程序基础) 小节中所做的那样),编译器也会将该文件视为一个代码箱。代码箱可以包含模组,而模组可以定义在与该代码箱一起编译的其他文件中,正如我们将在接下来的小节中看到的那样。 -我们要介绍的模组系统头两个部分,分别是代码包与代码箱。 +代码箱可以有两种形式:二进制代码箱或库代码箱。所谓 *二进制代码箱,binary crates*,属于可以咱们编译为咱们可运行的可执行文件的程序,例如命令行程序或服务器。每个二进制代码箱都必须有个名为 `main` 的函数,定义可执行文件运行时会发生什么。到目前为止我们创建的所有代码箱都属于二进制代码箱。 -*代码箱,crate* 是 Rust 编译器一次要考虑的最小代码量。即使咱们运行的是 `rustc` 而不是 `cargo`,并只传递了一个源代码文件(就像我们在第 1 章 “编写和运行 Rust 程序” 小节中所做的那样),编译器也会将该文件,视为一个代码箱。代码箱可以包含模组,模组也可以定义在与该代码箱一起编译的其他文件中,正如我们将在接下来的小节中看到的那样。 +所谓 *库代码箱,library crates*,没有 `main` 函数,并且他们不会编译为可执行文件。相反,他们定义了意图在多个项目中共享的功能。例如,我们在 [第 2 章](../Ch02_Programming_a_Guessing_Game.md#生成随机数) 中用到 `rand` 代码箱就提供了生成随机数的功能。大多数时候,Rustaceans 说 “代码箱,crate” 时,他们指的是库代码箱,并且他们会将 “代码箱” 与一般编程概念的 “库,library” 互换使用。 -代码箱有两种形式:二进制代码箱或库代码箱。*二进制代码箱,binary crates* 属于可以编译成咱们可以运行的可执行文件的程序,例如命令行程序或服务器。每个二进制代码箱,都必须有个名为 `main` 的函数,定义出可执行文件运行时会发生什么。到目前为止,我们创建的所有代码箱,都是二进制代码箱。 +所谓 *代码箱根,crate root*,是 Rust 编译器开始之处的源代码文件,并构成了咱们代码箱的 *根模组,root module*(我们将在 [在模组下控制作用域及隐私](/packages_crates_and_modules/defining_modules.md) 处深入解释模组)。 -*库代码箱,library crates* 没有 `main` 函数,也不会编译成可执行文件。相反,他们定义了旨在与多个项目共享的功能。例如,我们在 [第 2 章](../Ch02_Programming_a_Guessing_Game.md#生成随机数) 中,使用的 `rand` 代码箱,就提供了生成随机数的功能。大多数时候,当 Rustaceans 说 “代码箱,crate” 时,他们指的是库代码箱,而且他们会将 “代码箱”,与一般的编程概念 “库,library” 互换使用。 +所谓 *包,package*,是提供一组功能的一或多个代码箱的捆绑。包会包含一个 `Cargo.toml` 文件,描述如何构建这些代码箱。Cargo 实际上是个包,包含着咱们用来构建代码的命令行工具的二进制包。Cargo 包还包含了二进制代码箱所依赖的库代码箱。其他项目可依赖 Cargo 库代码箱,使用 Cargo 命令行工具使用的同样逻辑。 -而 *代码箱根,crate root*,则是个 Rust 编译器开始之处的源代码文件,并构成了咱们代码箱的 *根模组,root module*(我们将在 [定义控制作用域和隐私的模组](/packages_crates_and_modules/defining_modules.md) 小节,深入探讨模组)。 +一个包可以包含任意数量的二进制代码箱,但最多只有一个库代码箱。一个包必须至少包含一个代码箱,无论是库还是二进制代码箱。 -*包,package* 是提供了一组功能的一或多个代码箱的捆绑。包会包含一个描述如何构建这些代码箱的 `Cargo.toml` 文件。Cargo 实际上就是个包含了,咱们用来构建代码的命令行工具的包。Cargo 包还包含该二进制代码箱所依赖的库代码箱。其他项目可以依赖于 Cargo 的库代码箱,使用与 Cargo 这个命令行工具,所使用的同样逻辑。 - -一个包可以包含任意数量的二进制代码箱,但最多只能包含一个库代码箱。一个包必须至少包含一个代码箱,无论是库代码箱,还是二进制代码箱。 - -我们来看看,在我们创建某个软件包时,会发生什么。首先,我们输入命令 `cargo new`: +我们来看看当我们创建包时会发生什么。首先,我们输入命令 `cargo new my-project`: ```console -$ cargo new my-project --vcs=none - Created binary (application) `my-project` package +$ cargo new my-project + Creating binary (application) `my-project` package +note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html $ ls my-project Cargo.toml src $ ls my-project/src @@ -30,9 +28,9 @@ main.rs ``` -运行 `cargo new` 后,我们使用 `ls` 查看 Cargo 创建了什么。在该项目目录中,有个 `Cargo.toml` 文件,给到我们一个包。还有个包含了 `main.rs` 的 `src` 目录。请用咱们的文本编辑器,打开 `Cargo.toml`,注意其中没有提到 `src/main.rs`。Cargo 遵循,`src/main.rs` 是与该软件包同名的二进制代码箱的代码箱根,这一惯例。同样,Cargo 知道,如果包目录中包含 `src/lib.rs`,那么该包中就包含一个,与该包同名的库代码箱,而 `src/lib.rs` 就是其代码箱根。Cargo 会将代码箱根文件,传递给 `rustc` 以构建出该库或二进制程序。 +在我们运行 `cargo new` 后,我们使用 `ls` 来查看 Cargo 创建了什么。在 `my-project` 目录下,有个 `Cargo.toml` 文件,给到我们一个包。还有个包含 `main.rs` 的 `src` 目录。请以咱们的文本编辑器打开 `Cargo.toml`,注意其中没有提到 `src/main.rs`。Cargo 遵循一项约定,即 `src/main.rs` 是与包同名的二进制代码箱的代码箱根。同样,Cargo 知道当包目录包含 `src/lib.rs` 时,那么该包就包含一个与包同名的库代码箱,并且 `src/lib.rs` 即为其代码箱根。Cargo 会传递代码箱根文件给 `rustc` 以构建库或二进制程序。 -这里,我们有着一个只包含 `src/main.rs` 的包,意味着他只包含一个名为 `my-project` 的二进制代码箱。如果某个包包含 `src/main.rs` 和 `src/lib.rs`,那么他就有两个代码箱:一个二进制代码箱和一个库代码箱,且两个代码箱都有着与该包同样的名字。通过在 `src/bin` 目录中放置一些文件,包可以有多个二进制代码箱:每个文件都将是个单独的二进制代码箱。 +在这里,我们有个仅包含 `src/main.rs` 的包,这意味着他仅包含一个名为 `my-project` 的二进制代码箱。当某个包包含 `src/main.rs` 及 `src/lib.rs` 时,那么他就有两个代码箱:一个二进制代码箱和一个库代码箱,二者均有着与包相同的名字。通过放置文件与 `src/bin` 目录下,一个包可以有着多个二进制代码箱:每个文件都将是个单独的二进制代码箱。 (End)