diff --git a/append_end.sh b/append_end.sh
new file mode 100644
index 0000000..32e6d38
--- /dev/null
+++ b/append_end.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+PWD="$(pwd)"
+for f in $(find "src/" -type f -name "*.md" ); do
+ if [[ "${f}" == *"SUMMARY"* ]] || [[ "${f}" == *"README"* ]]; then continue; fi
+ echo -e "\n\n(End)\n\n" >> "$PWD/$f"
+done
diff --git a/src/404.md b/src/404.md
index 81e2d94..b8bfba5 100644
--- a/src/404.md
+++ b/src/404.md
@@ -7,3 +7,8 @@
This URL is invalid, sorry. Please use the navigation bar or search to continue. It will be redirected to home in n seconds...
+
+
+(End)
+
+
diff --git a/src/Ch00_Forword_and_Introduction.md b/src/Ch00_Forword_and_Introduction.md
index 99d915a..b8ef953 100644
--- a/src/Ch00_Forword_and_Introduction.md
+++ b/src/Ch00_Forword_and_Introduction.md
@@ -115,3 +115,8 @@ Rust 语言希望也能支持许多其他用户;这里提到的只是一些最
## 本书的源码
本书所产生的源码,可在 [Github: gnu4cn/rust-lang](https://github.com/gnu4cn/rust-lang-zh_CN/releases/tag/v0.2.0) 下载到。
+
+
+(End)
+
+
diff --git a/src/Ch01_Getting_Started.md b/src/Ch01_Getting_Started.md
index 435f84e..d7b3f0c 100644
--- a/src/Ch01_Getting_Started.md
+++ b/src/Ch01_Getting_Started.md
@@ -7,3 +7,8 @@
- 编写一个打印出 `Hello, world!` 的程序;
- 使用 Rust 的包管理器与构建系统 Cargo 。
+
+
+(End)
+
+
diff --git a/src/Ch02_Programming_a_Guessing_Game.md b/src/Ch02_Programming_a_Guessing_Game.md
index af9007d..6749ecd 100644
--- a/src/Ch02_Programming_a_Guessing_Game.md
+++ b/src/Ch02_Programming_a_Guessing_Game.md
@@ -835,3 +835,8 @@ fn main() {
这个项目以实践的方式,向咱们介绍了许多新的 Rust 概念:`let`、`match`、函数、外部代码箱的使用等等。在接下来的几章中,咱们将更详细地了解这些概念。第 3 章涵盖了大多数编程语言都有的概念,如变量、数据类型和函数等,并展示了如何在 Rust 中使用他们。第 4 章探讨了所有权,这是 Rust 不同于其他语言的一个特性。第 5 章会讨论结构体和方法语法,第 6 章解释了枚举的工作原理。
+
+
+(End)
+
+
diff --git a/src/Ch03_Common_Programming_Concepts.md b/src/Ch03_Common_Programming_Concepts.md
index 0885df3..60a9dd6 100644
--- a/src/Ch03_Common_Programming_Concepts.md
+++ b/src/Ch03_Common_Programming_Concepts.md
@@ -10,3 +10,8 @@
> **关键字,keywords**
>
> 与其他语言一样,Rust 语言也有一套仅供这门语言使用的 *关键字,keywords*。请记住,咱们不能将这些关键字,用作变量或函数的名字。大多数关键字,都有特殊含义,而咱们将在咱们的 Rust 程序中,使用他们完成各种任务;少数关键字目前没有与其相关的功能,但已被保留用于将来可能添加到 Rust 中的功能。咱们可以在 [附录 A](appendix/keywords.md) 中,找到这些关键字的列表。
+
+
+(End)
+
+
diff --git a/src/Ch04_Understanding_Ownership.md b/src/Ch04_Understanding_Ownership.md
index 610cce7..3a1cacb 100644
--- a/src/Ch04_Understanding_Ownership.md
+++ b/src/Ch04_Understanding_Ownership.md
@@ -3,3 +3,8 @@
**Understanding Ownership**
所有权是 Rust 最独特的特性,对语言的其他部分有着深刻的影响。他使 Rust 可以在不需要垃圾回收器的情况下,保证内存安全,因此了解所有权的工作原理非常重要。在本章中,我们将讨论所有权,以及几个相关特性:借用、切片,与 Rust 如何将数据放置于内存中。
+
+
+(End)
+
+
diff --git a/src/Ch05_Using_Structs_to_Structure_Related_Data.md b/src/Ch05_Using_Structs_to_Structure_Related_Data.md
index 5d64ad7..9ec79d1 100644
--- a/src/Ch05_Using_Structs_to_Structure_Related_Data.md
+++ b/src/Ch05_Using_Structs_to_Structure_Related_Data.md
@@ -5,3 +5,8 @@
结构体,`struct`,或 *structure*,是一种自定义数据类型,允许咱们将多个构成一个有意义的组的相关值,打包在一起并取个名字。如果咱们熟悉某门面向对象的语言,那么一个 `struct` 就像是某个对象的数据属性。在本章中,我们把元组与结构体进行对比,以在咱们已有知识的基础上,说明结构体在何时是更好的数据组织方式。
我们将演示如何定义和实例化结构体。我们将讨论如何定义关联函数,尤其是称为 *方法,methods* 的关联函数,以指定出与某个结构体类型相关的行为。结构体和枚举(会在第 6 章中讨论),是在咱们程序域中,创建出新类型,以充分利用 Rust 的编译时类型检查的两个基本构建模块。
+
+
+(End)
+
+
diff --git a/src/Ch06_Enums_and_Pattern_Matching.md b/src/Ch06_Enums_and_Pattern_Matching.md
index 5559c67..982c3ee 100644
--- a/src/Ch06_Enums_and_Pattern_Matching.md
+++ b/src/Ch06_Enums_and_Pattern_Matching.md
@@ -4,3 +4,8 @@
在本章中,我们将介绍 *枚举,enumerations*,也称为 *枚举,enums*。枚举允许咱们,通过枚举出其可能的 *变种,variants*,来定义某种类型。首先,我们将定义并使用一个枚举,以展示枚举如何与数据一起,编码意义。接下来,我们将探究一个名为 `Option` 的特别有用的枚举,他表示某个值可以是某物,也可以是无。然后,我们将了解 `match` 表达式中的模式匹配,如何使我们可以轻松地针对枚举的不同值,运行不同代码。最后,我们将介绍 `if let` 结构,怎样成为咱们代码中,处理枚举的另一方便简洁的习惯用法。
+
+
+(End)
+
+
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 adeb7af..69e31c8 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
@@ -24,3 +24,8 @@ Rust 有数项特性,可以让咱们管理咱们代码的组织,包括哪些
在本章中,我们将介绍所有这些功能,讨论他们如何交互,并探讨如何使用他们来管理作用域。到本章结束时,咱们应对模组系统有扎实的了解,并能像专业人士一样,使用作用域!
+
+
+(End)
+
+
diff --git a/src/Ch08_Common_Collections.md b/src/Ch08_Common_Collections.md
index c812613..783246d 100644
--- a/src/Ch08_Common_Collections.md
+++ b/src/Ch08_Common_Collections.md
@@ -11,3 +11,8 @@ Rust 标准库中包含了几种名为 *集合(collections)* 的有用数据
要了解由标准库所提供的其他类别集合,请参阅 [文档](https://doc.rust-lang.org/std/collections/index.html)。
这里将讨论怎样创建与更新矢量、字符串与哈希映射,同时会讨论他们因何而变得特殊。
+
+
+(End)
+
+
diff --git a/src/Ch09_Error_Handling.md b/src/Ch09_Error_Handling.md
index c7f39e2..2a69f8e 100644
--- a/src/Ch09_Error_Handling.md
+++ b/src/Ch09_Error_Handling.md
@@ -5,3 +5,8 @@
Rust 将错误分组为两个主要类别: *可恢复(recoverable)* 与 *不可恢复(unrecoverable)* 错误。对于可恢复错误,比如 *文件未找到* 错误,大多数情况下只要将该故障汇报给用户,并重试该操作。而不可恢复错误则总是代码错误的表征,像是尝试访问超出数组末端的某个位置,进而因此就要立即停止该程序。
大多数语言都没有区分这两种错误,而以同样方式,使用诸如异常的机制处理这两种错误。Rust 没有异常。相反,Rust 有着用于可恢复错误的类型 `Result`,以及在程序发生了不可恢复错误时,停止程序执行的 `panic!` 宏(the `panic!` macro)。本章将首先涵盖对 `panic!` 的调用,并在随后讲解那些返回的 `Result` 值。此外,这里会对在决定是否要尝试从错误中恢复,还是要停止程序的执行时的诸多考虑,进行探讨。
+
+
+(End)
+
+
diff --git a/src/Ch10_Generic_Types_Traits_and_Lifetimes.md b/src/Ch10_Generic_Types_Traits_and_Lifetimes.md
index f9231a0..0961507 100644
--- a/src/Ch10_Generic_Types_Traits_and_Lifetimes.md
+++ b/src/Ch10_Generic_Types_Traits_and_Lifetimes.md
@@ -120,3 +120,8 @@ fn main() {
接下来,就要在泛型下,使用这些同样步骤来降低代码重复了。与函数体可以在抽象的 `list`, 而非具体值上运作的方式一样,泛型实现了代码在抽象类型上的操作。
比如,假设说这里有两个函数:一个时在 `i32` 值的切片中,找出极大项,而另一个是在 `char` 值的切片中,找出极大项。那该怎样消除重复呢?下面就来解决这个问题!
+
+
+(End)
+
+
diff --git a/src/Ch11_Writing_Automated_Tests.md b/src/Ch11_Writing_Automated_Tests.md
index 3628021..b17d2af 100644
--- a/src/Ch11_Writing_Automated_Tests.md
+++ b/src/Ch11_Writing_Automated_Tests.md
@@ -9,3 +9,8 @@
可编写出进行假定的一些测试来,比如,在将 `3` 传递给这个 `add_two` 函数时,返回的值就是 `5`。每当修改了代码时,就都可以运行这些测试,来确保车关系的任何既有正确行为,没有发生变化。
测试是门综合技能:尽管这里无法在一章中,涉及到怎样编写良好测试的方方面面,这里还是会对 Rust 各种测试设施的机制进行讨论。这里会讲到在编写测试时,可用的注解与宏,运行测试的默认动作与选项,以及怎样将一些测试,组织为单元测试与集成测试(unit tests and integration tests)。
+
+
+(End)
+
+
diff --git a/src/Ch12_An_IO_Project_Building_a_Command_Line_Program.md b/src/Ch12_An_IO_Project_Building_a_Command_Line_Program.md
index 6a32e64..d527fdc 100644
--- a/src/Ch12_An_IO_Project_Building_a_Command_Line_Program.md
+++ b/src/Ch12_An_IO_Project_Building_a_Command_Line_Program.md
@@ -17,3 +17,8 @@ Rust 的速度、安全性、单一二进制可执行程序输出,还有跨平
- 编写测试([第 11 章](Ch11_Writing_Automated_Tests.md))
这里还会简要对闭包、迭代器及特质对象等,进行简要介绍,后面的 [第 13 章](Ch13_Functional_Languages_Features_Iterator_and_Closures.md) 与 [第 17 章](Object_Oriented_Programming_Features_of_Rust.md) 等章节,将详细讲解到这些特性。
+
+
+(End)
+
+
diff --git a/src/Ch13_Functional_Language_Features_Iterators_and_Closures.md b/src/Ch13_Functional_Language_Features_Iterators_and_Closures.md
index 78d67ff..c785806 100644
--- a/src/Ch13_Functional_Language_Features_Iterators_and_Closures.md
+++ b/src/Ch13_Functional_Language_Features_Iterators_and_Closures.md
@@ -12,3 +12,8 @@ Rust 的设计曾受到许多现有的语言和技术的启发,而一个显著
- 闭包与迭代器的性能问题(剧透警告:他们比咱们可能想的要快!)。
咱们已经讲到过其他的一些 Rust 特性,诸如模式匹配与枚举等,也是受函数式编程影响的。由于掌握闭包与迭代器,是编写惯用、快速 Rust 代码的重要方面,因此咱们将把这整章,都用来讲解他们。
+
+
+(End)
+
+
diff --git a/src/Ch14_More_about_Cargo_and_Crates-io.md b/src/Ch14_More_about_Cargo_and_Crates-io.md
index 732d5bd..1f4d3fa 100644
--- a/src/Ch14_More_about_Cargo_and_Crates-io.md
+++ b/src/Ch14_More_about_Cargo_and_Crates-io.md
@@ -12,3 +12,8 @@
相比咱们在本章会讲到的功能,Cargo 甚至能完成更多,因此对于 Cargo 全部特性的完整阐释,请参阅 [他的文档](https://doc.rust-lang.org/cargo/)。
+
+
+(End)
+
+
diff --git a/src/Ch15_Smart_Pointers.md b/src/Ch15_Smart_Pointers.md
index e03c195..7199a1b 100644
--- a/src/Ch15_Smart_Pointers.md
+++ b/src/Ch15_Smart_Pointers.md
@@ -21,3 +21,8 @@
此外,咱们还将讨论 *内部可变性,interior mutability* 模式,在这种模式下,不可变的类型会暴露出一个用于改变内部值的 API。我们还将讨论引用循环:他们如何泄漏内存以及如何防止他们。
下面就来切入正题吧!
+
+
+(End)
+
+
diff --git a/src/Ch16_Fearless_Concurrency.md b/src/Ch16_Fearless_Concurrency.md
index 840e103..b128b22 100644
--- a/src/Ch16_Fearless_Concurrency.md
+++ b/src/Ch16_Fearless_Concurrency.md
@@ -19,3 +19,8 @@
- *状态共用,shared-state* 方面的并发,其中多个线程均对某个数据加以访问;
- `Sync` 与 `Send` 特质,他们俩把 Rust 并发方面的保证,扩展到 Rust 使用者所定义的类型,以及由标准库所提供的那些类型。
+
+
+(End)
+
+
diff --git a/src/Ch17_Object_Oriented_Programming_Features_of_Rust.md b/src/Ch17_Object_Oriented_Programming_Features_of_Rust.md
index 6670155..dfd3479 100644
--- a/src/Ch17_Object_Oriented_Programming_Features_of_Rust.md
+++ b/src/Ch17_Object_Oriented_Programming_Features_of_Rust.md
@@ -3,3 +3,8 @@
**Object Oriented Programming Features of Rust**
面向对象编程方法,object-oriented programming, OOP, 是建模程序的一种方法。对象是在 20 世纪 60 年代,在编程语言 Simula 中所引入的一个程序化概念。正是那些对象,影响了 Alan Kay 的编程架构,其中对象会相互传递消息。为描述这种架构,他在 1967 年创造了面向对象编程这个术语。有许多互相竞争的定义,都描述了 OOP 是什么,而根据其中一些定义,Rust 属于面向对象的,但根据另一些,Rust 则不属于面向对象的。在本章中,咱们将探讨通常被看作是面向对象的一些特征,以及这些特征怎样被转译为 Rust 的习惯说法。随后咱们将给出在 Rust 怎样实现面向对象的设计模式,并讨论在这样做,与相反采用 Rust 的一些长处来实现解决方案,之间的权衡取舍。
+
+
+(End)
+
+
diff --git a/src/Ch18_Patterns_and_Matching.md b/src/Ch18_Patterns_and_Matching.md
index 45f86b7..c4c4108 100644
--- a/src/Ch18_Patterns_and_Matching.md
+++ b/src/Ch18_Patterns_and_Matching.md
@@ -21,3 +21,8 @@
要运用某个模式,咱们就要将其与某个值比较。在该模式与那个值匹配时,咱们在咱们的代码中,使用这个值的那些部分。回顾第 6 章中用到模式的那些 `match` 表达式,比如那个硬币分类机器示例。在值满足模式形状时,咱们就可以使用那些命名的代码片段。而在不满足时,与该模式关系的代码就不会运行。
本章时与模式相关全部内容的一个参考。咱们将涵盖运用模式的那些有效位置、可证伪与不可证伪模式的区别,the difference between refutable and irrefutable patterns,以及可能见到的那些不同类别的模式语法。在本章最后,咱们将获悉,如何运用模式来清晰地表达许多概念。
+
+
+(End)
+
+
diff --git a/src/Ch19_Advanced_Features.md b/src/Ch19_Advanced_Features.md
index e2b555e..96c5396 100644
--- a/src/Ch19_Advanced_Features.md
+++ b/src/Ch19_Advanced_Features.md
@@ -18,3 +18,8 @@
本章是给每个人应该了解的,一整套 Rust 特性!咱们就开始吧!
+
+
+(End)
+
+
diff --git a/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md b/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md
index 290be3c..04feaa2 100644
--- a/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md
+++ b/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md
@@ -26,3 +26,8 @@
在咱们开始动手前,咱们应注意到一个情况:咱们将运用的方法,将不会是在 Rust 下构建 web 服务器的最佳方法。在 [crates.io](https://crates.io/) 上,一些社区成员已经发布了数个,适合用于生产环境,提供了更完整功能的 web 服务器,以及咱们将要构建的线程池实现的代码箱。但是,本章中咱们的意图,是要帮助咱们学习掌握,而非走那样的捷径。由于 Rust 是门系统编程语言,因此咱们可以选择咱们打算着手的抽象层次,并可以触及到相比其他语言中,可行的或可操作的更低级别。因此咱们将亲自编写这个基本的 HTTP 服务器与线程池,如此咱们便可以学习这些代码箱之后的,今后可能会用到的一些一般概念与技巧。
+
+
+(End)
+
+
diff --git a/src/Ch21_Appendix.md b/src/Ch21_Appendix.md
index e797052..764dbba 100644
--- a/src/Ch21_Appendix.md
+++ b/src/Ch21_Appendix.md
@@ -1,3 +1,8 @@
# 附录
以下小节包含了在咱们的 Rust 路途中,会发现有用的一些参考资料。
+
+
+(End)
+
+
diff --git a/src/advanced_features/adv_fns_and_closures.md b/src/advanced_features/adv_fns_and_closures.md
index d21a09b..75d5bf9 100644
--- a/src/advanced_features/adv_fns_and_closures.md
+++ b/src/advanced_features/adv_fns_and_closures.md
@@ -132,3 +132,8 @@ fn returns_closure() -> Box i32> {
接下来,咱们就要看看宏了!
+
+
+(End)
+
+
diff --git a/src/advanced_features/adv_traits.md b/src/advanced_features/adv_traits.md
index 6f114f0..3f11ee3 100644
--- a/src/advanced_features/adv_traits.md
+++ b/src/advanced_features/adv_traits.md
@@ -475,3 +475,8 @@ fn main() {
即使不牵涉到特质,这种新型模式也是有用的。接下来就要转换一下视角,而看看与 Rust 的类型系统交互的一些高级方式。
+
+
+(End)
+
+
diff --git a/src/advanced_features/adv_types.md b/src/advanced_features/adv_types.md
index 7447870..e4e8577 100644
--- a/src/advanced_features/adv_types.md
+++ b/src/advanced_features/adv_types.md
@@ -248,3 +248,8 @@ fn generic(t: &T) {
还要注意咱们已将那个参数 `t` 的类型,从 `T` 更换为了 `&T`。由于这个类型可能不是 `Sized`,因此咱们就需要在某种指针之后使用他。在这种情况下,咱们选择了一个引用。
接下来,咱们将谈谈函数与闭包!
+
+
+(End)
+
+
diff --git a/src/advanced_features/macros.md b/src/advanced_features/macros.md
index 4d2904f..a832501 100644
--- a/src/advanced_features/macros.md
+++ b/src/advanced_features/macros.md
@@ -364,3 +364,8 @@ pub fn sql(input: TokenStream) -> TokenStream {
接下来,咱们将把这正本书中曾讨论过的所有内容,投入到实践中,而完成另一个项目!
+
+
+(End)
+
+
diff --git a/src/advanced_features/unsafe.md b/src/advanced_features/unsafe.md
index 8263cad..e146c6c 100644
--- a/src/advanced_features/unsafe.md
+++ b/src/advanced_features/unsafe.md
@@ -449,3 +449,8 @@ fn main() {}
运用 `unsafe` 来采取上述五种做法(超能力)没有什么过错,或者不受欢迎。但由于编译器无法助力于保持内存安全,因此要让 `unsafe` 代码正确就更为棘手一些。在有使用 `unsafe` 代码的某种理由时,就可以这样做,而在问题出现时,显式的 `unsafe` 注解,就会令到排查问题原因更为容易。
+
+
+(End)
+
+
diff --git a/src/appendix/derivable_traits.md b/src/appendix/derivable_traits.md
index 664b734..c1ca1c5 100644
--- a/src/appendix/derivable_traits.md
+++ b/src/appendix/derivable_traits.md
@@ -114,3 +114,8 @@
`Default::default` 函数,通常是与第 5 章中 [“使用结构体更新语法从其他实例创建出实例”](Ch05_Using_Structs_to_Structure_Related_Data.md#使用结构体更新语法从其他实例创建出实例) 小节里曾讨论过的结构体更新语法结合使用的。咱们可以定制结构体的几个字段,并在随后通过使用 `..Default::default()`,为其余字段设置并使用默认值。
在 `Option` 实例上使用 `unwrap_or_default` 方法时,便是需要 `Default` 特质的一个示例。当那个 `Option` 为 `None` 时,方法 `unwrap_or_default` 就将返回存储在 `Option` 中,那个类型 `T` 的 `Default::default` 结果。
+
+
+(End)
+
+
diff --git a/src/appendix/dev_tools.md b/src/appendix/dev_tools.md
index 82295dc..66ea457 100644
--- a/src/appendix/dev_tools.md
+++ b/src/appendix/dev_tools.md
@@ -160,3 +160,8 @@ fn main() {
为帮助 IDE 集成,Rust 社区建议使用 [`rust-analyzer`](https://rust-analyzer.github.io/)。此工具是一套以编译器为中心,操 [语言服务器协议,Language Server Protocol](http://langserver.org/) 的实用工具;而所谓语言服务器协议,则是用于各种 IDEs 和编程语言,二者相互之间通信的一种规格。有多种不同客户端可使用 `rust-analyzer`,比如 [Visual Studio Code 的 Rust 分析器插件](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)。
请访问 `rust-analyzer` 项目 [主页](https://rust-analyzer.github.io/),了解其安全说明,随后在咱们的特定 IDE 中安装该语言的服务器支持。咱们的 IDE 就能获得诸如自动补全、跳至定义及行内报错等能力。
+
+
+(End)
+
+
diff --git a/src/appendix/editions.md b/src/appendix/editions.md
index 8f30660..f675fff 100644
--- a/src/appendix/editions.md
+++ b/src/appendix/editions.md
@@ -25,3 +25,8 @@ Rust 语言及编译器有着六周的发布周期,意味着用户会得到源
要明确的是:绝大多数特性,在所有版本上都将可用。使用任何 Rust 版本的开发者,都将在新的稳定发布构造出来时,发现一些改进。但是,在一些情况下,主要是在新曾了关键字时,一些新特性就会只在稍后版本中可用了。若咱们打算利用上这些新特性,咱们将需要切换版本。
有关更多细节,[版本指南,Edition Guide](https://doc.rust-lang.org/stable/edition-guide/) 是本列举了不同版本间差异,并解释了怎样通过 `cargo fix`,而自动将咱们的代码更新到新版的一本完整的书。
+
+
+(End)
+
+
diff --git a/src/appendix/keywords.md b/src/appendix/keywords.md
index 058ed1b..100c4e6 100644
--- a/src/appendix/keywords.md
+++ b/src/appendix/keywords.md
@@ -116,3 +116,8 @@ fn main() {
此代码将不带任何错误地编译。请注意那个函数的定义中,与 `main` 中该函数被调用处其名字上的 `r#` 前缀。
原始标识符实现了将任何咱们所选的词语用作标识符,即使那个词语碰巧是个保留的关键字。这给到咱们更自由地选择标识符名字,以及实现与一些以其中这些词语不属于关键字的语言,所编写的程序集成。此外,原始标识符实现了,对那些以不同于咱们代码箱 Rust 版本编写库加以运用。比如,在 2015 版中 `try` 就不是个关键字,但在 2018 版本中却是。若咱们依赖于一个使用 2015 版本编写的库,而该库有一个 `try` 函数,那么咱们就将需要在这种情况下,使用原始标识符 `r#try`,来从咱们的 2018 版本的代码,调用那个函数。请参阅 [附录 E](#appendix-e) 了解更多有关版本的信息。
+
+
+(End)
+
+
diff --git a/src/appendix/notes.md b/src/appendix/notes.md
index d6fa24e..64e00ae 100644
--- a/src/appendix/notes.md
+++ b/src/appendix/notes.md
@@ -41,3 +41,8 @@ $ rustup component add llvm-tools-preview
```
+
+
+(End)
+
+
diff --git a/src/appendix/ops_and_symbols.md b/src/appendix/ops_and_symbols.md
index cb2639d..bdc2085 100644
--- a/src/appendix/ops_and_symbols.md
+++ b/src/appendix/ops_and_symbols.md
@@ -200,3 +200,8 @@
| `[type; len]` | 包含着 `len` 个 `type` 的实例数组的字面值 |
| `expr[expr]` | 对集合进行索引,collection indexing。是可过载的 `(Index, IndexMut)`,overloadable `(Index, IndexMut)` |
| `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | 用到了 `Range`、`RangeFrom`、`RangeTo` 或 `RangeFull` 作为 “索引”的,带有集合切片集合索引,collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, or `RangeFull` as the "index" |
+
+
+(End)
+
+
diff --git a/src/appendix/releases.md b/src/appendix/releases.md
index 781fe50..af2eea1 100644
--- a/src/appendix/releases.md
+++ b/src/appendix/releases.md
@@ -139,3 +139,8 @@ $ rustup override set nightly
若该特性被接受了,就会在 Rust 代码仓库上开出一个 issue,同时某个人就可以实现他。将其实现得非常棒的那个人,可能不是最早提议这项特性的那人!在实现准备好时,其就会落地于 `master` 分支的特性门,a feature gate,之后,如同咱们曾在 [“不稳定特性”](#不稳定特性) 小节中曾讨论过的那样。
过了一段时间后,一旦那些用到每日发布的 Rust 开发者们,能够试用这项新特性,那么 Rust 团队成员将讨论这项特性,怎样将其编制到每日发布上,并决定其是否有那个被构造到稳定发布 Rust。而若决定是继续推进,那么特性门就会被移除,同时这项特性就被认为是稳定的了!他就会搭上列车,进到一个新的稳定发布 Rust 中。
+
+
+(End)
+
+
diff --git a/src/appendix/terminology_list.md b/src/appendix/terminology_list.md
index 67bce52..b301f9f 100644
--- a/src/appendix/terminology_list.md
+++ b/src/appendix/terminology_list.md
@@ -162,3 +162,8 @@ Input lifetimes,函数或方法上的生命周期
- 输出生命周期
Output lifetimes, 返回值上的生命周期
+
+
+(End)
+
+
diff --git a/src/appendix/translations.md b/src/appendix/translations.md
index 0831616..6f27517 100644
--- a/src/appendix/translations.md
+++ b/src/appendix/translations.md
@@ -2,3 +2,8 @@
<略>
+
+
+(End)
+
+
diff --git a/src/automated_tests/how_tests_are_run.md b/src/automated_tests/how_tests_are_run.md
index 1f2abd5..9527254 100644
--- a/src/automated_tests/how_tests_are_run.md
+++ b/src/automated_tests/how_tests_are_run.md
@@ -377,3 +377,8 @@ running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
+
+
+(End)
+
+
diff --git a/src/automated_tests/howto.md b/src/automated_tests/howto.md
index 9f25fb3..84f5241 100644
--- a/src/automated_tests/howto.md
+++ b/src/automated_tests/howto.md
@@ -790,3 +790,8 @@ mod tests {
既然咱们已经了解了编写测试的几种方式,那么就来看一下,在运行这些编写的测试时会发生什么,并探索一下可与 `cargo test` 一起使用的不同选项。
+
+
+(End)
+
+
diff --git a/src/automated_tests/test_organization.md b/src/automated_tests/test_organization.md
index 02e0343..13b4acd 100644
--- a/src/automated_tests/test_organization.md
+++ b/src/automated_tests/test_organization.md
@@ -271,3 +271,8 @@ fn it_adds_two() {
Rust 的这些测试特性,提供到一种指明代码应如何生效,从而确保即使在进行了修改时,其仍继续如预期那样工作的方式。单元测试对库的各个部分进行单独检查,而可对一些私有实现细节进行测试。集成测试则对库的多个部分一起正确运作进行检查,同时他们会使用库的公开 API,以与外部代码使用库的同样方式,对代码进行测试。即使 Rust 的类型系统与所有权规则有助于防止某些种类的代码错误,对于消除与所编写代码预期表现方式有关的逻辑错误,测试仍是必不可少的。
下面就来将本章以及前面那些章中所掌握的知识结合起来,在一个项目上练手一下了!
+
+
+(End)
+
+
diff --git a/src/common_collections/hash_maps.md b/src/common_collections/hash_maps.md
index edf444d..1f58b75 100644
--- a/src/common_collections/hash_maps.md
+++ b/src/common_collections/hash_maps.md
@@ -256,3 +256,8 @@ error: could not compile `hashmap_demo` due to 2 previous errors
标准库 API 文档对矢量、字符串及哈希图有着的、对这些练习将有帮助的方法都有说明!
接下来就要进入到一些其中某些操作可能失败的程序,那么现在就是讨论错误处理的最佳时机。下一章就要来完成对错误处理的讨论了!
+
+
+(End)
+
+
diff --git a/src/common_collections/strings.md b/src/common_collections/strings.md
index f698181..f4df6f4 100644
--- a/src/common_collections/strings.md
+++ b/src/common_collections/strings.md
@@ -356,3 +356,8 @@ thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З
总的来说,字符串是复杂的。不同编程语言,在以何种程度将这种复杂度呈现给编程者上,做出了不同的选择。Rust 选择了将正确处理 `String` 数据,作为所有 Rust 程序的默认行为,这就意味着 Rust 程序员就必须在处理 UTF-9 数据时,要提前投入更多思考。这种权衡暴露了相较于其他编程语言,更多的字符串复杂度,但这防止了在软件开发生命周期后期,将涉及到的非 ASCII 字符的错误处理。
接下来就要换到,有点复杂的东西:哈希图!
+
+
+(End)
+
+
diff --git a/src/common_collections/vectors.md b/src/common_collections/vectors.md
index 5b5cc61..ecc1afb 100644
--- a/src/common_collections/vectors.md
+++ b/src/common_collections/vectors.md
@@ -214,3 +214,8 @@ Rust 需要在编译时了解那个矢量中会有些什么类型,这样他就
下面就移步到下一种集合类型:`String` 吧!
+
+
+(End)
+
+
diff --git a/src/concurrency/extensible_concurrency.md b/src/concurrency/extensible_concurrency.md
index 22974ec..a05a53d 100644
--- a/src/concurrency/extensible_concurrency.md
+++ b/src/concurrency/extensible_concurrency.md
@@ -48,3 +48,8 @@
Rust 标准库提供了用于消息传递的信道,以及诸如 `Mutex` 与 `Arc` 等安全用于并发情景中的一些灵巧指针类型。类型系统与借用检查器,会确保应用了这些方案的代码,不会以数据竞争或无效引用结束。一旦让代码编译了,咱们就可以放下心来,代码将愉快地运行于多线程之上,而不会有在其他语言中常见的那些难于追踪的问题。并发编程自此不再是令人害怕的概念:去吧,让你的程序并发起来,无所畏惧!
接下来,咱们将讲到,随着咱们的 Rust 程序变得大了起来,建模问题与架构出方案的一些管用做法。此外,咱们将讨论 Rust 的一些习惯说法,这些说法可能与面向对象编程中所熟悉的有关。
+
+
+(End)
+
+
diff --git a/src/concurrency/message_passing.md b/src/concurrency/message_passing.md
index 9ee742a..fd686e9 100644
--- a/src/concurrency/message_passing.md
+++ b/src/concurrency/message_passing.md
@@ -271,3 +271,8 @@ fn main() {
根据咱们所在系统的不同,也可能会看到另外顺序的这些值。这种消息每次出现顺序的不一致,正是令到并发有趣而又有难度的地方。而若带上 `thread::sleep` 加以实验,即在两个不同线程中给到不同睡眠值,这时的每次运行,将更具不确定性,而每次运行都造成不同输出。
既然咱们已经看到了信道的工作原理,那么接下来就要看看一种方式迥异的并发了。
+
+
+(End)
+
+
diff --git a/src/concurrency/shared-state.md b/src/concurrency/shared-state.md
index e5ba3dc..1e008a9 100644
--- a/src/concurrency/shared-state.md
+++ b/src/concurrency/shared-state.md
@@ -266,3 +266,8 @@ fn main() {
另一个需要注意的细节,便是在咱们使用 `Mutex` 时,Rust 无法保护咱们免于全部类别的逻辑错误。回顾在第 15 章中,`Rc` 运用就伴随着创建出循环引用风险,其中两个 `Rc` 值相互指向,导致内存泄漏。与此类似,`Mutex` 则附带着创建出 *死锁,deadlocks* 的风险。在某个操作需要锁住两项资源,同时两个线程分别均已请求获取两把锁中的一把时,就造成他们一直等待着对方释放各自所需的锁。若对死锁方面感兴趣,那么请尝试创建出有着死锁的一个 Rust 程序;随后就要研究任何一门语言中,互斥量的死锁消除策略,并试试在 Rust 中实现这些策略。`Mutex` 和 `MutexGuard` 的标准库 API 文档,就提供了一些有用信息。
咱们将通过讲解 `Send` 与 `Sync` 两个特质,以及怎样与一些定制类型来运用他们来完结本章。
+
+
+(End)
+
+
diff --git a/src/concurrency/threads.md b/src/concurrency/threads.md
index b0f1399..53f8793 100644
--- a/src/concurrency/threads.md
+++ b/src/concurrency/threads.md
@@ -320,3 +320,8 @@ error: could not compile `concur_demo` due to previous error
Rust 的所有权规则,再次挽救了咱们!由于 Rust 一直以来的保守,以及只为那个线程借用了 `v`,就意味着主线程理论上可以令到生成线程的引用失效,而得到了清单 16-3 中代码的报错。通过告知 Rust 将 `v` 的所有权迁移到生成线程,咱们就向 Rust 保证了主线程不会再使用 `v`。而若咱们以同样方式修改清单 16-4,那么随后在咱们于主线程中尝试使用 `v` 时,就破坏了那些所有权规则。这个 `move` 关键字,覆盖了 Rust 借用方面的保守做法;但他并无让咱们破坏所有权规则。
有了线程及线程 API 方面的基本认识,接下来就有看看用线程可以 *做,do* 些什么。
+
+
+(End)
+
+
diff --git a/src/crates-io/cargo_install.md b/src/crates-io/cargo_install.md
index 5a01614..749a2cd 100644
--- a/src/crates-io/cargo_install.md
+++ b/src/crates-io/cargo_install.md
@@ -74,3 +74,8 @@ $ cargo install ripgrep
```
输出的倒数第二行显示出已安装二进制程序的位置与名字,在这个示例中名字便是 `rg`。正如前面提到的,只要安装目录是在 `$PATH` 中,随后咱们就可以运行 `rg --help`,并启动一个用于检索文件的更快、更具 Rust 风格的工具了!
+
+
+(End)
+
+
diff --git a/src/crates-io/custom_commands.md b/src/crates-io/custom_commands.md
index 5af6c20..a3dc129 100644
--- a/src/crates-io/custom_commands.md
+++ b/src/crates-io/custom_commands.md
@@ -8,3 +8,8 @@ Cargo 被设计为在无需修改 Cargo 下,咱们就可以使用新的子命
# 本章小结
运用 Cargo 与 [crates.io](https://crates.io) 分享代码,是令到 Rust 生态对于许多不同任务都有用的一个方面。Rust 的标准库是小型且稳定的,但在不同于语言本身的时间线上,代码箱则易于共享、运用以及改进。请不要羞于在 [crates.io](https://crates.io) 上分享对自己有用的代码;那些代码或许对其他人也同样有用!
+
+
+(End)
+
+
diff --git a/src/crates-io/publishing.md b/src/crates-io/publishing.md
index 3864519..bc93c7b 100644
--- a/src/crates-io/publishing.md
+++ b/src/crates-io/publishing.md
@@ -443,3 +443,8 @@ $ cargo yank --vers 0.1.0 --undo
```
抽出版本,*不会* 删除任何代码。比如,其无法删除那些不小心上传的机密信息。若发生了机密信息被上传的情况,咱们必须立即重置这些机密信息。
+
+
+(End)
+
+
diff --git a/src/crates-io/release_profiles.md b/src/crates-io/release_profiles.md
index 84d7b05..0d0f00c 100644
--- a/src/crates-io/release_profiles.md
+++ b/src/crates-io/release_profiles.md
@@ -44,3 +44,8 @@ opt-level = 1
此代码会覆盖默认设置 `0`。现在当咱们运行 `cargo build` 时,Cargo 将使用 `dev` 配置文件的默认设置,加上咱们对 `opt-level` 的定制。由于咱们把 `opt-level` 设置为了 `1`,Cargo 将应用相比于默认设置更多,但不如发布构建那样多的优化。
对于各个配置文件的完整配置项清单与默认设置,请参阅 [Cargo 文档](https://doc.rust-lang.org/cargo/reference/profiles.html)。
+
+
+(End)
+
+
diff --git a/src/crates-io/workspace.md b/src/crates-io/workspace.md
index 2898a24..bc1f1cd 100644
--- a/src/crates-io/workspace.md
+++ b/src/crates-io/workspace.md
@@ -302,3 +302,8 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini
作为附加练习,请以与 `add_one` 代码箱类似方式,把 `add_two` 添加到这个工作区!
当咱们的项目日渐增长时,请考虑使用工作区:相比于一大块代码,要搞清楚较小的、单独的组件就更容易一些。再者,当代码箱经常同时被修改时,把这些代码箱保持在工作区中,就能令到他们之间的协作更容易。
+
+
+(End)
+
+
diff --git a/src/enums_and_pattern_matching/defining_an_enum.md b/src/enums_and_pattern_matching/defining_an_enum.md
index e92579c..e7cb4fb 100644
--- a/src/enums_and_pattern_matching/defining_an_enum.md
+++ b/src/enums_and_pattern_matching/defining_an_enum.md
@@ -295,3 +295,8 @@ error: could not compile `option_demo` (bin "option_demo") due to previous error
那么,当咱们有着某个 `Option` 类型的值时,该怎样从 `Some` 变种中获取到那个 `T` 值,以便使用该值呢?`Option` 这个枚举,有着大量在不同场景下,都有用的方法;咱们可以在 [其文档](https://doc.rust-lang.org/std/option/enum.Option.html) 中,查看这些方法。熟悉 `Option` 的方法,将对咱们的 Rust 之旅大有裨益。
一般来说,为了使用某个 `Option` 值,咱们需要编写处理每个变种的代码。咱们会想要一些,仅在咱们有个 `Some(T)` 值时才会运行的代码,而这些代码,就可以使用内部的 `T` 值;咱们会想要另一些,只有在咱们有个 `None` 值时才会运行的代码,而这些代码就没有可用的 `T` 值。与枚举一起使用的 `match` 表达式,便是一种正好完成这个目的的控制流结构:他会根据枚举有着哪一个变种,而运行不同的代码,而这些代码,就可以使用匹配值内部的数据。
+
+
+(End)
+
+
diff --git a/src/enums_and_pattern_matching/if-let_control_flow.md b/src/enums_and_pattern_matching/if-let_control_flow.md
index b7fa736..dce5dc5 100644
--- a/src/enums_and_pattern_matching/if-let_control_flow.md
+++ b/src/enums_and_pattern_matching/if-let_control_flow.md
@@ -80,3 +80,8 @@ if let Coin::Quarter(state) = coin {
咱们的 Rust 程序现在可以使用结构体和枚举,来表达咱们领域中的概念了。在咱们的 API 中创建一些自定义类型,确保了类型安全:编译器将确保咱们的函数,只获取到每个他们所期望类型的值。
为了向咱们的用户,提供组织良好、简单易用的 API,并且只暴露出咱们用户所需的内容,我们现在来看看 Rust 的模组。
+
+
+(End)
+
+
diff --git a/src/enums_and_pattern_matching/match_control_flow.md b/src/enums_and_pattern_matching/match_control_flow.md
index 5627890..747b13c 100644
--- a/src/enums_and_pattern_matching/match_control_flow.md
+++ b/src/enums_and_pattern_matching/match_control_flow.md
@@ -287,3 +287,8 @@ fn remove_fancy_hat() {}
在这里,我们显式地告诉 Rust,我们不会使用,任何与先前支臂中模式不匹配的其他值,且在这种情况下,我们不打算运行任何代码。
我们将在 [第 18 章](../Ch18_Patterns_and_Matching.md) 中,结束更多有关模式与匹配的内容。现在,我们将继续讨论 `if let` 这种语法,其在 `match` 表达式显得有些冗长的情况下,非常有用。
+
+
+(End)
+
+
diff --git a/src/error_handling/panic.md b/src/error_handling/panic.md
index 491b00e..653f4e1 100644
--- a/src/error_handling/panic.md
+++ b/src/error_handling/panic.md
@@ -104,3 +104,8 @@ note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose bac
在上面清单 9-2 里的输出中,回溯所指向到这里项目中行的第 6 行,就是导致问题的行:即 `src/main.rs` 的第 4 行。在不想要这个程序中止时,就应在首个提到了自己所编写文件的行,所指向的那个位置,开始排查。在之前的清单 9-1 中,那里有意编写了会中止的代码,而修正程序中止的办法,就是不要请求某个超出那个矢量索引范围的元素。而在今后代码中止时,就需要搞清楚代码是在对什么值进行何种操作,而导致了中止,以及代码应该怎么做。
在本章的 [要 `panic!` 或不要 `panic!`](#要-panic-还是不要-panic) 小节,将回到 `panic!` 这个话题,并讨论在何时要用 `panic!`,何时不应使用 `panic!` 来处理不同错误情形。接下来,就会看看怎样使用 `Result`,从错误中恢复过来。
+
+
+(End)
+
+
diff --git a/src/error_handling/panic_or_not.md b/src/error_handling/panic_or_not.md
index 43f2bfe..790efe9 100644
--- a/src/error_handling/panic_or_not.md
+++ b/src/error_handling/panic_or_not.md
@@ -134,3 +134,8 @@ impl Guess {
Rust 的那些错误处理特性,被设计用于帮助编写更为健壮的代码。`panic!` 这个宏,发出了程序处于其无法处理状态的信号,并让咱们告知进程停下来,而不是尝试以无效或不正确的一些值继续运行。而 `Result` 这个枚举则使用了 Rust 的类型系统,来表示以代码可以从中恢复过来的某种方式的一些操作失败(the `Result` enum uses Rust's type system to indicate that operations might fail in a way that your code could recover from)。还可使用 `Result` 来告诉调用了咱们代码的代码,需要处理潜在的成功与失败情形。在一些适当情形下,运用 `panic!` 与 `Result` 就会令到咱们的代码在各种不可避免的问题面前,更加可靠。
既然这里已经见识到标准库在 `Option` 与 `Result` 枚举上,运用到泛型的一些有用方式,那么接下来就要谈及泛型的原理,以及怎样在咱们的代码中运用泛型。
+
+
+(End)
+
+
diff --git a/src/error_handling/result.md b/src/error_handling/result.md
index 53df9d0..e2c7695 100644
--- a/src/error_handling/result.md
+++ b/src/error_handling/result.md
@@ -414,3 +414,8 @@ fn main() -> Result<(), Box> {
+
+
+(End)
+
+
diff --git a/src/final_project/graceful_shutdown.md b/src/final_project/graceful_shutdown.md
index 9b0989c..7389810 100644
--- a/src/final_project/graceful_shutdown.md
+++ b/src/final_project/graceful_shutdown.md
@@ -451,3 +451,8 @@ impl Worker {
# 本章小结
干得好!咱们已经读完了这整本书!要感谢咱们加入到这次 Rust 之旅中来。咱们现在已经准备好实现咱们自己的 Rust 项目,以及帮助其他人的项目了。请记住有那么一个由热衷于就咱们在 Rust 道路上,所遇到的任何挑战,而帮助咱们的其他 Rust 公民的热情社区。
+
+
+(End)
+
+
diff --git a/src/final_project/multithreaded.md b/src/final_project/multithreaded.md
index 09683de..2db2770 100644
--- a/src/final_project/multithreaded.md
+++ b/src/final_project/multithreaded.md
@@ -721,3 +721,8 @@ impl Worker {
这段代码将会编译及运行,但不会产生所需的线程行为:慢速请求仍将导致别的请求等待被处理。至于原因则有点微妙:由于锁的所有权是基于 `lock` 方法返回的 `LockResult>` 中,`MutexGuard` 的生命周期,因此这个 `Mutex` 结构体没有公开的 `unlock` 方法。在编译时,借用检查器可于随后,就除非咱们拿着 `Mutex` 所守卫的某项资源的锁,否则无法访问该项资源这一规则强制加以检查。但是,若咱们没有注意到 `MutexGuard` 的生命周期,那么这样的实现同样能导致锁相较预期被占用更长时间。
由于在 `let` 之下,等号右侧的表达式中用到的任何临时值,都会在 `let` 语句结束时被立即丢弃,因此使用了 `let job = receiver.lock().unwrap().recv().unwrap();` 的清单 20-20 中代码是工作的。但是,`while let`(以及 `if let` 与 `match`) 则是在相关代码块结束前,不会丢弃那些临时值。在清单 20-21 中,锁会在到 `job()` 的调用其将保持被持有,这意味着别的 `worker` 就没法收到作业。
+
+
+(End)
+
+
diff --git a/src/final_project/single-threaded.md b/src/final_project/single-threaded.md
index 07baa1d..4fcac25 100644
--- a/src/final_project/single-threaded.md
+++ b/src/final_project/single-threaded.md
@@ -455,3 +455,8 @@ fn handle_conn(mut stream: TcpStream) {
+
+
+(End)
+
+
diff --git a/src/functional_features/closures.md b/src/functional_features/closures.md
index a4f4b38..d5a75b9 100644
--- a/src/functional_features/closures.md
+++ b/src/functional_features/closures.md
@@ -492,3 +492,8 @@ fn main() {
println! ("{:#?}\n{:#?}", list, sort_operations);
}
```
+
+
+(End)
+
+
diff --git a/src/functional_features/improving_io_project.md b/src/functional_features/improving_io_project.md
index f8288c5..ca6795b 100644
--- a/src/functional_features/improving_io_project.md
+++ b/src/functional_features/improving_io_project.md
@@ -223,3 +223,8 @@ pub fn search_insensitive<'a>(
下一个合乎逻辑的问题是,咱们应在自己的代码中选择哪种风格与为什么:清单 13-21 中原本的实现,或清单 13-22 中用到迭代器的版本。大多数 Rust 程序员喜欢使用迭代器风格。一开始他有点难掌握,但一旦咱们对各种迭代器适配器和他们的作用有了感觉,迭代器就会更容易理解。该代码没有拨弄循环的各个部分,与构建出新的矢量值,而是专注于循环的高级目标。这就把一些普通的代码抽象化了,所以更容易看到这段代码特有的概念,比如迭代器中每个元素必须通过的过滤条件。
但是,这两种实现方式真的等同吗?直观的假设可能是,更低级别的循环会更快。接下来咱们就会谈及性能问题。
+
+
+(End)
+
+
diff --git a/src/functional_features/iterators.md b/src/functional_features/iterators.md
index ffb6cf7..16d5135 100644
--- a/src/functional_features/iterators.md
+++ b/src/functional_features/iterators.md
@@ -244,3 +244,8 @@ mod tests {
闭包从环境中捕获到 `shoe_size` 参数,并将该值与每双鞋子的尺码比较,只保留特定尺码的鞋子。最后,调用 `collect` 方法,将调整出的迭代器返回的 `Shoe` 类型值,收集到一个矢量中,`shoes_in_size` 函数返回的,便是这个矢量值。
测试表明,当咱们调用 `shoes_in_size` 时,只得到了与咱们指定的值相同大小的鞋子。
+
+
+(End)
+
+
diff --git a/src/functional_features/performance.md b/src/functional_features/performance.md
index ec2717a..f9f3f31 100644
--- a/src/functional_features/performance.md
+++ b/src/functional_features/performance.md
@@ -48,3 +48,8 @@ for i in 12..buffer.len() {
闭包与迭代器,是 Rust 受函数式编程概念启发的两项特性。他们有助于 Rust 以底层性能清楚表达高级别概念的能力。闭包与迭代器的实现,不会影响到运行时性能。这正是 Rust 致力于提供零成本抽象目标的一部分。
现在我们已经改进了 I/O 项目的表达能力,让我们再来看看 `cargo` 的更多特性,这些特性将帮助我们与世界分享这个项目。
+
+
+(End)
+
+
diff --git a/src/generic_types_traits_and_lifetimes/generics.md b/src/generic_types_traits_and_lifetimes/generics.md
index 3588ba0..07cb615 100644
--- a/src/generic_types_traits_and_lifetimes/generics.md
+++ b/src/generic_types_traits_and_lifetimes/generics.md
@@ -372,3 +372,8 @@ fn main() {
+
+
+(End)
+
+
diff --git a/src/generic_types_traits_and_lifetimes/lifetimes.md b/src/generic_types_traits_and_lifetimes/lifetimes.md
index b05ce99..28d6f09 100644
--- a/src/generic_types_traits_and_lifetimes/lifetimes.md
+++ b/src/generic_types_traits_and_lifetimes/lifetimes.md
@@ -572,3 +572,8 @@ where
在这一章中,咱们谈到了很多东西!现在咱们清楚了泛型参数、特质与特质边界,与泛型生命周期参数,那么就准备好编写在许多不同情况下工作,不带有重复的代码了。泛型参数实现了将代码应用于不同类型。特质与特质边界确保即使类型是通用的,他们仍将有着代码所需的行为。咱们了解了如何使用生命周期注解,来保证这种灵活代码不会有任何悬空引用。且所有分析,都发生在编译时,其不会影响到运行时性能!
不论相信与否,关于咱们在本章讨论的这些话题,要掌握的东西远不止这些:第 17 章会讨论特质对象,trait objects,其是运用特质的另一种方式。还有更多咱们只会在极复杂场景下,才需要的涉及到更复杂场景的生命周期注解;要了解那些生命周期注解,咱们应阅读 [Rust 指南](https://doc.rust-lang.org/reference/index.html)。不过接下来,咱们将了解怎样编写 Rust 中的测试,从而就可以确保所咱们的代码,以其应有的方式工作。
+
+
+(End)
+
+
diff --git a/src/generic_types_traits_and_lifetimes/traits.md b/src/generic_types_traits_and_lifetimes/traits.md
index e270342..a7a2087 100644
--- a/src/generic_types_traits_and_lifetimes/traits.md
+++ b/src/generic_types_traits_and_lifetimes/traits.md
@@ -392,3 +392,8 @@ let s = 3.to_string();
特质与特质边界这两个特性,允许咱们编写出运用泛型参数来减少代码重复的代码,并还向编译器指出了咱们希望该泛型有着特定行为。随后编译器就能使用特质边界信息,来检查代码用到的全部具体类型,是否提供到正确行为。在一般的动态类型语言,dynamically typed languages,中,若调用某个类型上尚未定义的方法,咱们将在运行时收到报错。但 Rust 将这些错误移到了编译时,这样在代码还不能运行的时候,咱们就被强制要求修复这些问题。此外,由于已在编译时被检查过,因此咱们就不必编写检查运行时行为的代码。这样做在提升了性能的同时,不必放弃泛型灵活性。
+
+
+(End)
+
+
diff --git a/src/getting_started/hello_cargo.md b/src/getting_started/hello_cargo.md
index 7fe951e..64a4a0d 100644
--- a/src/getting_started/hello_cargo.md
+++ b/src/getting_started/hello_cargo.md
@@ -212,3 +212,8 @@ $ cargo build
这正是编写一个更大型程序,来习惯于读写 Rust 代码的大好时机。因此,在第 2 章中,我们将构建一个猜数游戏程序。如果咱们想从掌握那些常见编程概念,在 Rust 中的工作原理开始,那么请参阅第 3 章,然后返回第 2 章。
+
+
+(End)
+
+
diff --git a/src/getting_started/hello_world.md b/src/getting_started/hello_world.md
index 5b1839f..6927230 100644
--- a/src/getting_started/hello_world.md
+++ b/src/getting_started/hello_world.md
@@ -162,3 +162,8 @@ $ ./main # 或在 Windows 上的 .\main.exe
如果咱们更熟悉 Ruby、Python 或 JavaScript 等某门动态语言,则可能不习惯于将编译和运行某个程序,作为单独的步骤。Rust 属于一门 *提前编译,ahead-of-time compiled* 语言,这意味着,你能够编译某个程序,并把可执行文件交给其他人,而即使他们没有安装 Rust,也可以运行这个可执行程序。而如果咱们给别人某个 `.rb`、`.py` 或 `.js` 文件,他们就需要分别安装 Ruby、Python 或 JavaScript 的某种实现。不过在这些语言中,咱们只需要一条命令,来编译并运行咱们的程序。在语言设计中,一切都需要权衡利弊,everything is a trade-off in language design。
对于简单程序,使用 `rustc` 编译就可以了,但随着项目的发展,咱们会希望管理所有选项,以及并方便共用咱们的代码。接下来,我们将介绍,将会帮助咱们编写真实世界 Rust 程序的 Cargo 工具。
+
+
+(End)
+
+
diff --git a/src/getting_started/installation.md b/src/getting_started/installation.md
index 99ad826..415dbbe 100644
--- a/src/getting_started/installation.md
+++ b/src/getting_started/installation.md
@@ -204,3 +204,8 @@ $ rustup self uninstall
Rust 的安装,还包含了一份本地文档,以便咱们离线阅读。请运行 `rustup doc`,在咱们的浏览器中打开本地文档。
如果咱们不确定,某个标准库提供的类型或函数的作用,或使用方法,请使用应用程序编程接口(API)文档来搞清楚!
+
+
+(End)
+
+
diff --git a/src/io_project/accepting_cli_arguments.md b/src/io_project/accepting_cli_arguments.md
index 10de958..577d9f9 100644
--- a/src/io_project/accepting_cli_arguments.md
+++ b/src/io_project/accepting_cli_arguments.md
@@ -108,3 +108,8 @@ $ cargo run -- test sample.txt
```
很好,这个程序工作了!所需参数的那些值正被保存到恰当的变量中。后面就要添加一些错误处理,来处理某些潜在的错误情形,诸如在用户未提供参数这样的情况;现在,这里将忽略那样的情况,而是会编写添加文件读取能力的代码。
+
+
+(End)
+
+
diff --git a/src/io_project/env_variables.md b/src/io_project/env_variables.md
index f0ee550..f88ddf6 100644
--- a/src/io_project/env_variables.md
+++ b/src/io_project/env_variables.md
@@ -237,3 +237,8 @@ To an admiring bog!
有的程序,同时实现同一配置的命令行参数 *与* 环境变量。在这样的情形下,这些程序就会确定下其中之一有着较高优先级。好比你自己的另一代码练习中,就会尝试经由命令行参数,或同时经由环境变量,对是否区分大小写进行控制。就会在程序在一种设置下区分大小写,而另一种设置下不区分大小写时,对到底命令行参数优先,还是环境变量优先,加以确定。
这个 `std::env` 模组,包含了许多用于处理环境变量的其他有用特性:请查看其文档来看看有哪些可用特性。
+
+
+(End)
+
+
diff --git a/src/io_project/reading_a_file.md b/src/io_project/reading_a_file.md
index db72a38..b1136b8 100644
--- a/src/io_project/reading_a_file.md
+++ b/src/io_project/reading_a_file.md
@@ -68,3 +68,8 @@ To an admiring bog!
```
很好!这代码就读取并于随后打印出了那个文件的内容。但这代码有着少数几个缺陷。此时的这个 `main` 函数,有着多重义务:一般来讲,在每个函数只负责一件事情时,那么他们就是些更为清晰明了,并更易于维护的函数了。另一问题则是这里没有尽可能地对错误进行处理。这个程序还很小,因此这些缺陷就不是什么大问题,不过随着程序变大,就会变得更加难于彻底修复这些缺陷。在开发某个程序时,由于重构数量较少的代码要容易得多,因此尽早开始重构,是一种良好实践。接下来就会干这件事 -- 重构。
+
+
+(End)
+
+
diff --git a/src/io_project/refactoring.md b/src/io_project/refactoring.md
index 0acbef5..14d10af 100644
--- a/src/io_project/refactoring.md
+++ b/src/io_project/refactoring.md
@@ -499,3 +499,8 @@ fn main() {
咦!这可是干了很多活了,还好现在已经为将来的成功做好了准备。现在处理错误就容易多了,同时令到代码更具模块性。从现在开始,几乎咱们的全部工作,就将在 `src/lib.rs` 完成了。
下面就来通过运用现在这种新发现的模组性优势,完成一些对于早先不具模组性代码较难实现,而对这新代码却易于实现的事情。
+
+
+(End)
+
+
diff --git a/src/io_project/std_err.md b/src/io_project/std_err.md
index 7a29728..603a7e8 100644
--- a/src/io_project/std_err.md
+++ b/src/io_project/std_err.md
@@ -101,3 +101,8 @@ How dreary to be somebody!
本章回顾了到目前为止曾学过的一些主要概念,并涵盖了在 Rust 中怎样完成常见 I/O 操作。经由使用命令行参数、文件、环境变量,以及那个用于打印错误的 `eprintln!` 宏,现在就已准备好编写命令行应用程序了。结合先前那些章中的概念,咱们所编写的代码将是良好组织、以恰当数据结构有效地存储着数据、对错误加以优美地处理,并被妥善地测试过。
接下来,这里将探讨受函数式编程所影响的一些 Rust 特性:闭包与迭代器(closures and iterators)。
+
+
+(End)
+
+
diff --git a/src/io_project/test_driven_dev.md b/src/io_project/test_driven_dev.md
index 2d5ff2a..ea17384 100644
--- a/src/io_project/test_driven_dev.md
+++ b/src/io_project/test_driven_dev.md
@@ -287,3 +287,8 @@ How dreary to be somebody!
相当棒!这里已经构建了一个经典工具自己的小型版本,并掌握了很多有关如何建构应用程序的知识。这里还了解到有关文件输入输出、生命周期、测试及命令行参数解析等方面的点滴内容。
而为了完善这个项目,接下来就主要会演示怎样使用环境变量,以及怎样打印到标准错误输出(print to standard error),在编写命令行程序时,这两方面的知识都是有用的。
+
+
+(End)
+
+
diff --git a/src/local_serving.md b/src/local_serving.md
index f016813..4fb6ce7 100644
--- a/src/local_serving.md
+++ b/src/local_serving.md
@@ -41,3 +41,8 @@ mdbook serve ~/rust-lang-zh_CN -p 8080 -n 127.0.0.1 --open
此时,将在操作系统的默认浏览器中,打开本书。
+
+
+(End)
+
+
diff --git a/src/oop/characteristics_oop.md b/src/oop/characteristics_oop.md
index 5e4c317..6db5894 100644
--- a/src/oop/characteristics_oop.md
+++ b/src/oop/characteristics_oop.md
@@ -106,3 +106,8 @@ impl AveragedCollection {
由于继承通常有着共用了超出必要代码的风险,时至今日,其已在许多编程语言中,作为编程设计模式而失宠了。子类本不应共用其父类的全部特征,但在继承父类时却会这样做。这就会造成程序的设计有较低的灵活性。由于子类从父类继承的一些方法并不适用于子类,因此继承还会引入调用子类上无意义或引发错误方法的可能。此外,一些语言还只将运行单一继承(即子类只能从一个类继承),这进一步限制了程序设计的灵活度。
由于这些原因,Rust 便采取了运用特质对象,而非继承的方法。接下来就要看看特质对象是如何实现 Rust 中的多态。
+
+
+(End)
+
+
diff --git a/src/oop/implementing.md b/src/oop/implementing.md
index d8374ee..341506f 100644
--- a/src/oop/implementing.md
+++ b/src/oop/implementing.md
@@ -521,3 +521,8 @@ fn main() {
在读完这一章之后,不论咱们认为或是不认为 Rust 是门面向对象语言,现在都明白,咱们可以在 Rust 中,使用特质对象来获得一些面向对象的特性。动态调遣,dynamic dispatch 可以些许运行时性能损失,换取到咱们代码一定程度的灵活性。咱们则可运用这样的灵活性,来实现能有助于代码可维护性的一些面向对象模式。Rust 还有面向对象语言所没有的其他一些特性,比如所有权等。对于利用 Rust 各种长处方面的优势来讲,面向对象模式将不总是最佳方式,但其为一种可行选项。
接下来,咱们将看看各种模式,这是带来大量灵活性的 Rust 诸多特性的另一项。虽然贯穿本书,咱们已经粗略地看了看他们,但仍尚未见识到他们的完整能力。咱们就拭目以待吧!
+
+
+(End)
+
+
diff --git a/src/oop/trait_objects.md b/src/oop/trait_objects.md
index 9321fcc..fb38294 100644
--- a/src/oop/trait_objects.md
+++ b/src/oop/trait_objects.md
@@ -233,3 +233,8 @@ error: could not compile `simple_gui` due to previous error
回顾第 10 章中 [“运用了泛型的代码性能问题”](Ch10_Generic_Types_Traits_and_Lifetimes.md#使用泛型参数代码的性能问题) 小节中,在泛型之上运用特质边界时,咱们关于由编译器所完成的单一化过程,the monomorphization process 的讨论:编译器会为咱们在泛型参数处,用到的各个具体类型,而产生出非通用的函数及方法实现。单一化过程所产生的代码,便是在进行 *静态调遣,static dispatch*,这是编译器清楚,咱们在编译时调用的为哪个方法时的情况。这与 *动态调遣,dynamic dispatch* 是相反的,动态调遣是编译器在编译时,无法区分出咱们所调用的为何方法时的情况。在动态调遣情况下,编译器产生出将在运行时,得出要调用方法的代码。
在咱们运用特质对象时,Rust 就必须使用动态调遣。对于全部可能与用到特质对象代码一起使用的类型,编译器并无掌握,因此他就不明白要调用何种类型上的哪个方法。相反,在运行时,Rust 会使用特质对象内部的指针,来掌握要调用哪个方法。这种做法会导致静态调遣下所不会发生的运行时开销。动态调遣还会阻止编译器内联某个方法代码的抉择,这就相应地阻止了一些优化。然而,咱们却真切地获得了,如同咱们在清单 17-5 中所编写的代码那样的灵活性,同时才能够支持清单 17-9 中那样的情况,如此其便是一种需要考量的取舍了。when we use trait objects, Rust must use dynamic dispatch. The compiler doesn't know all the types that might be used with the code that's using trait objects, so it doesn't know which method implemented on which type to call. Instead, at runtime, Rust uses the pointers inside the trait object to know which method to call. This lookup incurs a runtime cost that doesn't occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a method's code, which in turn prevents some optimizations. However, we did get extra flexibility in the code that we wrote in Listing 17-5 and were able to support in Listing 17-9, so it's a trade-off to consider.
+
+
+(End)
+
+
diff --git a/src/ownership/about_ownership.md b/src/ownership/about_ownership.md
index 00c605b..c207f49 100644
--- a/src/ownership/about_ownership.md
+++ b/src/ownership/about_ownership.md
@@ -475,3 +475,8 @@ fn calculate_length(s: String) -> (String, usize) {
*清单 4-5:返回参数的所有权*
但是,对于一个本应很常见的概念来说,这样做太过仪式化和工作量都太大了。幸运的是,Rust 有一种使用某个值,而不转移所有权的特性,叫做 *引用,references*。
+
+
+(End)
+
+
diff --git a/src/ownership/references_and_borrowing.md b/src/ownership/references_and_borrowing.md
index 6b8b5df..423e237 100644
--- a/src/ownership/references_and_borrowing.md
+++ b/src/ownership/references_and_borrowing.md
@@ -360,3 +360,8 @@ fn dangle() -> String {
接下来,我们来看看另一种引用:切片。
+
+
+(End)
+
+
diff --git a/src/ownership/the_slice_type.md b/src/ownership/the_slice_type.md
index 148bf9a..a24384e 100644
--- a/src/ownership/the_slice_type.md
+++ b/src/ownership/the_slice_type.md
@@ -347,3 +347,8 @@ fn main() {
所有权、借用和切片的概念,确保了 Rust 程序在编译时的内存安全。Rust 给到了咱们,与其他系统编程语言同样方式的,对咱们内存使用的掌控,但在数据的所有者超出作用域时,会让数据的所有者,自动清理该数据,这意味着咱们不必编写和调试额外代码,来获得这种控制。
所有权会影响 Rust 许多其他部分的工作方式,因此我们将在本书的其余部分,进一步讨论这些概念。我们来继续阅读第 5 章,看看如何在 `struct` 中,对数据块进行分组。
+
+
+(End)
+
+
diff --git a/src/packages_crates_and_modules/defining_modules.md b/src/packages_crates_and_modules/defining_modules.md
index e71750c..de88d83 100644
--- a/src/packages_crates_and_modules/defining_modules.md
+++ b/src/packages_crates_and_modules/defining_modules.md
@@ -149,3 +149,8 @@ crate
该树显示了其中一些模组是如何嵌套在另一模组中的;例如,`hosting` 嵌套在 `front_of_house` 中。该树还显示其中一些模组彼此属于 *同辈,siblings*,即他们被定义在同一模组中;`hosting` 和 `serving` 是 `front_of_house` 中定义的同辈份模组。如果模组 A 包含在模组 B 中,我们就说模组 A 是模组 B 的子模组,而模组 B 是模组 A 的父模组。请注意,整个模组树的根,都位于名为 `crate` 的隐式模组下。
模组树可能会让咱们联想到电脑上的文件系统目录树;这是个非常恰当的比较!就像文件系统中的目录一样,咱们可以使用模组来组织代码。而就像目录中的文件一样,我们需要一种找到咱们模组的方法。
+
+
+(End)
+
+
diff --git a/src/packages_crates_and_modules/packages_and_crates.md b/src/packages_crates_and_modules/packages_and_crates.md
index f54c728..46f2b53 100644
--- a/src/packages_crates_and_modules/packages_and_crates.md
+++ b/src/packages_crates_and_modules/packages_and_crates.md
@@ -33,3 +33,8 @@ 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` 以构建出该库或二进制程序。
这里,我们有着一个只包含 `src/main.rs` 的包,意味着他只包含一个名为 `my-project` 的二进制代码箱。如果某个包包含 `src/main.rs` 和 `src/lib.rs`,那么他就有两个代码箱:一个二进制代码箱和一个库代码箱,且两个代码箱都有着与该包同样的名字。通过在 `src/bin` 目录中放置一些文件,包可以有多个二进制代码箱:每个文件都将是个单独的二进制代码箱。
+
+
+(End)
+
+
diff --git a/src/packages_crates_and_modules/paths.md b/src/packages_crates_and_modules/paths.md
index 60d62fb..10270df 100644
--- a/src/packages_crates_and_modules/paths.md
+++ b/src/packages_crates_and_modules/paths.md
@@ -323,3 +323,8 @@ pub fn eat_at_restaurant() {
因为我们将这个 `Appetizer` 枚举构造为了公开,所以我们可以在 `eat_at_restaurant` 中,使用 `Soup` 和 `Salad` 两个变种。
除非枚举变种是公开的,否则枚举的用处就不大;如果每次都要给所有枚举变种注释上 `pub`,那就太烦人了,所以枚举变种默认是公开的。通常结构体在其字段不公开的情况下也很有用,因此结构体字段遵循了一般规则,即除非被注释为 `pub`,否则默认情况下所有字段,都是私有的。
+
+
+(End)
+
+
diff --git a/src/packages_crates_and_modules/separating_modules.md b/src/packages_crates_and_modules/separating_modules.md
index 9ad3c0d..69107c0 100644
--- a/src/packages_crates_and_modules/separating_modules.md
+++ b/src/packages_crates_and_modules/separating_modules.md
@@ -84,3 +84,8 @@ pub fn add_to_waitlist() {}
Rust 实现了包拆分为多个代码箱,进而将代码箱拆分为多个模组,这样就可以从一个模组,对定义在另一模组中的程序项目加以引用。通过指明绝对或相对路径,就可以做到这点。使用 `use` 语句,就可以将这些程序项目的路径,带入到作用域,如此就可以在那个作用域中,多次用到所带入的程序项目时,使用较简短的路径。默认下模组代码是私有的,但可通过添加 `pub` 关键字,而将一些定义构造为公开的。
下一章中,就会看看,可在本地组织良好代码中,使用到的标准库中的一些集合数据结构(collection data structures)。
+
+
+(End)
+
+
diff --git a/src/packages_crates_and_modules/the_use_keyword.md b/src/packages_crates_and_modules/the_use_keyword.md
index 40878ce..d0c19f3 100644
--- a/src/packages_crates_and_modules/the_use_keyword.md
+++ b/src/packages_crates_and_modules/the_use_keyword.md
@@ -304,3 +304,8 @@ use std::collections::*;
这条 `use` 语句会将 `std::collections` 中定义的所有公开项目引入当前作用域。使用全局操作符时要当心!全局性会使咱们更难分辨,哪些名称是在作用域中,以及程序中使用的名字是在何处定义。
全局操作符通常在测试时使用,以便将所有被测试内容引入 `tests` 模块;我们将在第 11 章 [“如何编写测试”](../automated_tests/howto.md#怎样编写测试) 小节中讨论这个问题。全局操作符有时也作为前奏模式,the prelude pattern,的一部分使用:有关该模式的更多信息,请参阅 [标准库文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes)。
+
+
+(End)
+
+
diff --git a/src/patterns/all_places.md b/src/patterns/all_places.md
index 2faede6..2acfa60 100644
--- a/src/patterns/all_places.md
+++ b/src/patterns/all_places.md
@@ -240,3 +240,8 @@ fn main() {
由于如咱们在第 13 章中曾讨论过的,闭包与函数类似,咱们也可以函数参数清单中的这同样方式,在闭包参数清单中使用模式。
到这里,咱们就已经看到了运用模式的数种方式,但在咱们可使用他们的每种地方,模式并非以同样方式运作。在一些地方,模式必须是确凿的,must be irrefutable;而在别的情况下,他们则可以是可证伪的,can be refutable。接下来咱们就将讨论这两个概念。
+
+
+(End)
+
+
diff --git a/src/patterns/refutability.md b/src/patterns/refutability.md
index f7173b8..2729839 100644
--- a/src/patterns/refutability.md
+++ b/src/patterns/refutability.md
@@ -89,3 +89,8 @@ warning: `refutable_demo` (bin "refutable_demo") generated 1 warning
由于这个原因,除了应以一个不可证伪模式匹配全部剩余值的最后支臂外,其他那些匹配支臂,就必须使用可证伪模式。Rust 允许咱们在仅有一个支臂的 `match` 中,使用不可证伪模式,但这种语法不是特别有用,并可以一个更简单的 `let` 语句替换。
现在,咱们就知道了哪些地方要使用模式,以及可证伪与不可证伪模式的区别,下面就来介绍所有可用于创建模式的语法。
+
+
+(End)
+
+
diff --git a/src/patterns/syntax.md b/src/patterns/syntax.md
index 0d7bb61..e1a80d3 100644
--- a/src/patterns/syntax.md
+++ b/src/patterns/syntax.md
@@ -666,3 +666,8 @@ fn main() {
Rust 的模式,在区分不同类别数据方面非常有用。当在 `match` 表达式中用到模式时,Rust 就会确保咱们的那些模式,涵盖每个可能的值,否则咱们的程序便不会编译。`let` 语句与函数参数中的模式,会令到这两种结构更为有用,在实现值解构为一些更小的部分的同时,赋值给一些变量。咱们可以创建出简单抑或复杂的模式,来适合咱们的需求。
接下来,作为本书倒数第二章,咱们将数种 Rust 特性中,一些高级的方面。
+
+
+(End)
+
+
diff --git a/src/programming_concepts/comments.md b/src/programming_concepts/comments.md
index 8c4d0b0..1a6ec26 100644
--- a/src/programming_concepts/comments.md
+++ b/src/programming_concepts/comments.md
@@ -46,3 +46,8 @@ fn main() {
```
Rust 还有另一种注释,即文档注释,documentation comments,我们将在第 14 章 [“将 Crate 发布到 Crates.io”](../crates-io/publishing.md) 一节中讨论。
+
+
+(End)
+
+
diff --git a/src/programming_concepts/control_flow.md b/src/programming_concepts/control_flow.md
index 305b9b0..68db119 100644
--- a/src/programming_concepts/control_flow.md
+++ b/src/programming_concepts/control_flow.md
@@ -719,3 +719,8 @@ fn main() {
```
+
+
+(End)
+
+
diff --git a/src/programming_concepts/data_types.md b/src/programming_concepts/data_types.md
index 34b3139..7fa8017 100644
--- a/src/programming_concepts/data_types.md
+++ b/src/programming_concepts/data_types.md
@@ -435,3 +435,8 @@ error: process didn't exit successfully: `target\debug\tuple_demo.exe` (exit cod
该程序在索引操作中,使用某个无效值时,出现了 *运行时* 错误。程序以一条错误信息退出了,并且没有执行最后的那条 `println!` 语句。当咱们尝试使用索引访问某个元素时,Rust 会检查咱们指定的索引,是否小于数组长度。如果索引大于或等于长度,Rust 就会终止运行。这种检查必须在运行时进行,尤其是在这种情况下,因为编译器不可能知道,某名用户在他们稍后运行代码时,会输入什么值。
这是 Rust 内存安全原则,实际应用的一个例子。在许多底层语言中,并无这种检查,而当咱们提供了某个不正确的索引时,无效内存就会被访问到。Rust 通过立即退出,而不是允许这种内存访问并继续,保护咱们免受此类错误的影响。第 9 章将讨论更多的 Rust 错误处理,以及如何编写既不会终止运行,也不允许无效内存访问的,可读安全代码。
+
+
+(End)
+
+
diff --git a/src/programming_concepts/functions.md b/src/programming_concepts/functions.md
index 6bc7ca9..5093e94 100644
--- a/src/programming_concepts/functions.md
+++ b/src/programming_concepts/functions.md
@@ -347,3 +347,8 @@ error: could not compile `functions` (bin "functions") due to previous error
其中的主要错误信息,`mismatched types`,揭示了这段代码的核心问题。函数 `plus_one` 的定义,说他将返回一个 `i32`,但语句不会计算为某个值,而是由 `()` 表示的单元值,the unit type。因此,没有返回任何值,这与函数定义相矛盾,而导致一个报错。在此输出中,Rust 提供了一条,可能有助于纠正此问题的信息:他建议删除分号,这就将会修复这个错误。
+
+
+(End)
+
+
diff --git a/src/programming_concepts/variables_and_mutability.md b/src/programming_concepts/variables_and_mutability.md
index 4e12780..254ee75 100644
--- a/src/programming_concepts/variables_and_mutability.md
+++ b/src/programming_concepts/variables_and_mutability.md
@@ -227,3 +227,8 @@ error: could not compile `variables` (bin "variables") due to previous error
现在我们已经探讨了变量的工作原理,我们来看看,他们可以拥有的更多数据类型。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/box-t.md b/src/smart_pointers/box-t.md
index fdb83a8..3e426e0 100644
--- a/src/smart_pointers/box-t.md
+++ b/src/smart_pointers/box-t.md
@@ -181,3 +181,8 @@ fn main() {
匣子仅提供这种间接与内存堆的内存分配;他们不具备任何像咱们在其他灵巧指针类型中,将看到的其他特别能力。他们也没有这些特殊能力所带来的性能开销,所以在像构造列表这样的情况下,他们就能很有用,因为间接性是我们唯一需要的功能。在第 17 章,咱们还会看一下匣子的更多用例。
`Box` 类型是一个智能指针,因为他实现了 `Deref` 特质,他允许 `Box` 值被当作引用。当 `Box` 值超出作用域时,由于 `Drop` 特质的实现,匣子所指向的内存堆数据也会被清理。这两个特质对于咱们在本章后面将讨论的其他灵巧指针所提供的功能,将更加重要。咱们来更深入地探讨这两个特质。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/deref-t.md b/src/smart_pointers/deref-t.md
index 7d7ad48..c41d5f8 100644
--- a/src/smart_pointers/deref-t.md
+++ b/src/smart_pointers/deref-t.md
@@ -270,3 +270,8 @@ fn main() {
前两种情况彼此相同,只是第二种情况实现了可变性。第一种情况表明,如果咱们有一个 `&T`,并且 `T` 实现了对某种类型 `U` 的 `Deref`,咱们可以透明地得到一个 `&U`。第二种情况表明相同的解引用强制转换发生在可变引用上。
第三种情况比较棘手:Rust 还会将可变引用强制转换为不可变引用。但反过来是 *不* 可行的:不可变引用永远不会强制转换为可变引用。由于借用规则,如果咱们有一个可变引用,则该可变引用必须是对那个数据的唯一引用(否则,程序将无法编译)。将一个可变引用转换为一个不可变引用永远不会违反借用规则。将不可变引用转换为可变引用,则要求那个初始不可变引用是对那个数据的唯一不可变引用,但借用规则并不能保证这一点。因此,Rust 不能假设将不可变引用转换为可变引用是可行的。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/drop-t.md b/src/smart_pointers/drop-t.md
index 721539b..46c7250 100644
--- a/src/smart_pointers/drop-t.md
+++ b/src/smart_pointers/drop-t.md
@@ -142,3 +142,8 @@ $ cargo run
咱们也不必担心因意外清理仍在使用的值而导致的问题:确保引用始终有效的所有权系统,还确保在值不再被使用时,`drop` 只被调用一次。
现在我们已经研究了 `Box` 和灵巧指针的一些特性,让我们看看标准库中定义的其他几个智能指针。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/rc-t.md b/src/smart_pointers/rc-t.md
index 59261c4..31f049f 100644
--- a/src/smart_pointers/rc-t.md
+++ b/src/smart_pointers/rc-t.md
@@ -138,3 +138,8 @@ $ cargo run
我们在这个例子中看不到的是,当 `b` 和 `a` 在 `main` 的末尾超出作用域时,计数为 `0`,并且 `Rc` 会被完全清除。使用 `Rc` 允许单个值拥有多个所有者,而计数确保只要任何所有者仍然存在,该值就保持有效。
通过不可变的引用,`Rc` 允许咱们在程序的多个部分之间共用数据,仅供读取。如果 `Rc` 还允许咱们有多个可变引用,咱们可能会违反第四章中讨论的一个借用规则:对同一个地方的多个可变借用,会导致数据竞赛和不一致。但是,能够修改数据是非常有用的!在下一节中,我们将讨论内部可变性模式和 `RefCell` 类型,咱们可以将其与 `Rc` 结合起来使用,以应对这种不可变性限制。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/ref-cycles.md b/src/smart_pointers/ref-cycles.md
index 2e792d3..0696131 100644
--- a/src/smart_pointers/ref-cycles.md
+++ b/src/smart_pointers/ref-cycles.md
@@ -240,3 +240,8 @@ children: RefCell { value: [] } }] } })
如果本章引起了你的兴趣,并且你想实现你自己的智能指针,请查看 ["The Rustonomicon"](https://doc.rust-lang.org/nomicon/index.html) ,以获得更多有用的信息。
接下来,我们将讨论 Rust 中的并发问题。咱们甚至会了解到一些新的灵巧指针。
+
+
+(End)
+
+
diff --git a/src/smart_pointers/refcell-t.md b/src/smart_pointers/refcell-t.md
index 44d455c..b74ed2e 100644
--- a/src/smart_pointers/refcell-t.md
+++ b/src/smart_pointers/refcell-t.md
@@ -279,3 +279,8 @@ $ cargo run lennyp@vm-manj
```
这个技巧非常整洁! 通过使用 `RefCell`,我们有一个对外不可变的 `List` 值。但是我们可以使用 `RefCell` 上提供对其内部可变性访问的方法,这样我们就可以在需要的时候修改我们的数据。借用规则的运行时检查可以保护我们不受数据竞赛的影响,有时值得用一点速度来换取我们数据结构中的这种灵活性。请注意,`RefCell` 对多线程代码不起作用! `Mutex` 是 `RefCell` 的线程安全版本,我们将在第 16 章讨论 `Mutex`。
+
+
+(End)
+
+
diff --git a/src/structs/defining_and_instantiating.md b/src/structs/defining_and_instantiating.md
index 70be7c4..30a1433 100644
--- a/src/structs/defining_and_instantiating.md
+++ b/src/structs/defining_and_instantiating.md
@@ -262,3 +262,8 @@ error: could not compile `structs_demo` due to 2 previous errors
```
> 在第 10 章中,我们将讨论如何修复这些报错,以便咱们在结构体中存储引用,但现在,我们将使用自有类型(如 `String`)而不是引用(如 `&str`),来修复这类报错。
+
+
+(End)
+
+
diff --git a/src/structs/example_program.md b/src/structs/example_program.md
index 3376cd9..0bd14ac 100644
--- a/src/structs/example_program.md
+++ b/src/structs/example_program.md
@@ -312,3 +312,8 @@ warning: `rectangles` (bin "rectangles") generated 1 warning
除了这个 `Debug` 特质外,Rust 还为我们提供了许多与这个 `derive` 属性配合使用的特质,这些特质可以为我们的自定义类型,添加有用的行为。[附录 C](../appendix/derivable_traits.md) 列出了这些特质及其行为。我们将在第 10 章,介绍如何使用自定义行为实现这些特质,以及如何创建咱们自己的特质。除了 `derive` 之外,还有许多其他属性;有关详细信息,请参阅 [《Rust 参考》中的 "属性 "部分](https://doc.rust-lang.org/reference/attributes.html)。
我们的 `area` 函数,是非常专门的:他只会计算矩形的面积。如果能将这一行为,与咱们的 `Rectangle` 结构体更紧密地联系在一起,将会很有帮助,因为他无法与任何其他类型一起工作。我们来看看,咱们可以怎样通过将这个 `area` 函数,转化为定义在 `Rectangle` 类型上的 `area` 方法,来继续重构这段代码。
+
+
+(End)
+
+
diff --git a/src/structs/method_syntax.md b/src/structs/method_syntax.md
index 65be575..b155a2a 100644
--- a/src/structs/method_syntax.md
+++ b/src/structs/method_syntax.md
@@ -243,3 +243,8 @@ impl Rectangle {
结构体可让咱们创建出,对咱们领域有意义的自定义类型。通过使用结构体,咱们可以将相关的数据片段,相互连接起来,并为每个片段命名,使咱们的代码清晰明了。在 `impl` 代码块中,咱们可以定义出,与咱们类型相关联的函数,而方法就是一种,可以让咱们指定出,结构体实例所具有行为的关联函数。
但是,结构体并不是咱们可以创建自定义类型的唯一方法:咱们来使用 Rust 的枚举特性,为咱们的工具箱添加另一种工具。
+
+
+(End)
+
+