Merge pull request #1 from KaiserY/master

sync upstream update
pull/176/head
Kelleg 7 years ago committed by GitHub
commit 0a3accfeec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,12 +1,16 @@
# Rust 程序设计语言 # Rust 程序设计语言
[前言](foreword.md)
[介绍](ch00-00-introduction.md)
## 入门指南 ## 入门指南
- [介绍](ch01-00-introduction.md) - [入门指南](ch01-00-getting-started.md)
- [安装](ch01-01-installation.md) - [安装](ch01-01-installation.md)
- [Hello, World!](ch01-02-hello-world.md) - [Hello, World!](ch01-02-hello-world.md)
- [Hello, Cargo!](ch01-03-hello-cargo.md)
- [猜猜看教程](ch02-00-guessing-game-tutorial.md) - [猜猜看游戏教程](ch02-00-guessing-game-tutorial.md)
- [通用编程概念](ch03-00-common-programming-concepts.md) - [通用编程概念](ch03-00-common-programming-concepts.md)
- [变量与可变性](ch03-01-variables-and-mutability.md) - [变量与可变性](ch03-01-variables-and-mutability.md)
@ -16,7 +20,7 @@
- [控制流](ch03-05-control-flow.md) - [控制流](ch03-05-control-flow.md)
- [认识所有权](ch04-00-understanding-ownership.md) - [认识所有权](ch04-00-understanding-ownership.md)
- [什么是所有权](ch04-01-what-is-ownership.md) - [什么是所有权](ch04-01-what-is-ownership.md)
- [引用与借用](ch04-02-references-and-borrowing.md) - [引用与借用](ch04-02-references-and-borrowing.md)
- [Slices](ch04-03-slices.md) - [Slices](ch04-03-slices.md)
@ -81,21 +85,21 @@
- [Cargo 自定义扩展命令](ch14-05-extending-cargo.md) - [Cargo 自定义扩展命令](ch14-05-extending-cargo.md)
- [智能指针](ch15-00-smart-pointers.md) - [智能指针](ch15-00-smart-pointers.md)
- [`Box<T>` 在堆上存储数据,并且可确定大小](ch15-01-box.md) - [`Box<T>` 指向堆上数据,并且可确定大小](ch15-01-box.md)
- [通过 `Deref` trait 将智能指针当作常规引用处理](ch15-02-deref.md) - [通过 `Deref` trait 将智能指针当作常规引用处理](ch15-02-deref.md)
- [`Drop` Trait 运行清理代码](ch15-03-drop.md) - [`Drop` Trait 运行清理代码](ch15-03-drop.md)
- [`Rc<T>` 引用计数智能指针](ch15-04-rc.md) - [`Rc<T>` 引用计数智能指针](ch15-04-rc.md)
- [`RefCell<T>` 内部可变性模式](ch15-05-interior-mutability.md) - [`RefCell<T>` 内部可变性模式](ch15-05-interior-mutability.md)
- [引用循环与内存泄漏](ch15-06-reference-cycles.md) - [引用循环与内存泄漏是安全的](ch15-06-reference-cycles.md)
- [无畏并发](ch16-00-concurrency.md) - [无畏并发](ch16-00-concurrency.md)
- [线程](ch16-01-threads.md) - [线程](ch16-01-threads.md)
- [消息传递](ch16-02-message-passing.md) - [消息传递](ch16-02-message-passing.md)
- [共享状态](ch16-03-shared-state.md) - [共享状态](ch16-03-shared-state.md)
- [可扩展的并发:`Sync``Send`](ch16-04-extensible-concurrency-sync-and-send.md) - [可扩展的并发:`Sync``Send`](ch16-04-extensible-concurrency-sync-and-send.md)
- [Rust 是面向对象语言吗?](ch17-00-oop.md) - [Rust 的面向对象编程特征](ch17-00-oop.md)
- [什么是面向对象?](ch17-01-what-is-oo.md) - [面向对象语言的特点](ch17-01-what-is-oo.md)
- [为使用不同类型的值而设计的 trait 对象](ch17-02-trait-objects.md) - [为使用不同类型的值而设计的 trait 对象](ch17-02-trait-objects.md)
- [面向对象设计模式的实现](ch17-03-oo-design-patterns.md) - [面向对象设计模式的实现](ch17-03-oo-design-patterns.md)
@ -125,3 +129,4 @@
- [D - 宏](appendix-04-macros.md) - [D - 宏](appendix-04-macros.md)
- [E - 本书翻译](appendix-05-translation.md) - [E - 本书翻译](appendix-05-translation.md)
- [F - 最新功能](appendix-06-newest-features.md) - [F - 最新功能](appendix-06-newest-features.md)
- [G - Rust 是如何开发的与 “Nightly Rust”](appendix-07-nightly-rust.md)

@ -0,0 +1 @@
# G - Rust 是如何开发的与 “Nightly Rust”

@ -0,0 +1,85 @@
# 介绍
> [ch00-00-introduction.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch00-00-introduction.md)
> <br>
> commit acc5ee25138531b030c6c4844de2b7066959021d
欢迎阅读 “Rust 程序设计语言”,一本介绍 Rust 的书。
Rust 是一门帮助你编写更快、更可靠软件的编程语言。高层工程学与底层控制在其他编程语言设计中往往是相互矛盾的通过平很强大的技术能力与优秀的开发体验Rust 提供了控制底层细节(比如内存使用)的选择,并免受通常随之而来的所有烦恼。
## 谁会使用 Rust
Rust 因多种原因适用于很多开发者。让我们讨论一些最为重要的群体。
### 开发者团队
Rust 被证明是可用于大型的拥有不同层次系统编程水平开发者团队的生产力工具。底层代码易于出现大量隐晦的 bug对于其他编程语言这只能通过广泛的测试和有经验开发者细心的代码评审才能加以捕获。在 Rust 中,编译器充当了守门员的角色,它拒绝编译存在这类难以捕获 bug 的代码,包括并发 bug。通过与编译器合作团队可以利用更多的时间专注于程序逻辑而不是追踪 bug。
Rust 也带来了用于系统编程世界的现代化开发工具:
* Cargo内置的依赖管理器和构建工具它可以毫无痛苦的增加、编译和管理依赖并使其在整个 Rust 生态系统中保持一致。
* Rustfmt 在开发者之间确保了一致的代码风格。
* Rust Language Server 为集成开发环境Integrated Development Environment, IDE提供了强大的代码补全和内联错误信息。
通过使用这些和其他一些 Rust 生态系统中的工具,开发者可以在编写系统级别代码时保持高生产力。
### 学生
Rust 适用于学生或任何对操作系统概念感兴趣的人。通过 Rust很多人已经了解了像操作系统开发这样的主题。社区非常欢迎并乐于解答学生们的问题。通过类似于本书这样的努力Rust 团队希望操作系统的概念为更多人所知,特别是那些对编程比较陌生的人。
### 公司
数以百计大大小小的公司正将 Rust 用于生产环境中的多种任务。这些任务包括命令行工具、web 服务、DevOps 工具、嵌入式设备、音视频分析与转码、数字货币cryptocurrencies、生物信息学bioinformatics、搜索引擎、物联网internet of things, IOT程序、机器学习甚至还包括 Firefox 浏览器的大部分内容。
### 开源开发者
Rust 适用于希望构建 Rust 编程语言、社区、开发工具和库的开发者。我们期望你为 Rust 语言做贡献。
### 重视速度和稳定性的开发者
Rust 适用于渴望编程语言的速度与稳定性的开发者。对于速度,我们指你自身可以通过 Rust 开发程序的速度和 Rust 允许你开发他们的速度。Rust 的编译器检查确保了增加功能和重构代码时的稳定性这与缺少这些检查的语言中开发者害怕修改那些脆弱的遗留代码形成了鲜明的对比。通过力求零成本抽象zero-cost abstractions高层次代码所编译的底层代码与手写的一样快Rust 力图使安全的代码也同样快速。
虽然我们没有提供一个所有人希望 Rust 语言支持的功能的完整列表这里提到的是一些最大的功能。总体上讲Rust 最大的理想在于消除数十年来程序员所习惯接受的那些一分为二的取舍:安全 **与** 生产力、速度 **与** 工程学。请尝试 Rust看看这些选择是否适合你。
## 谁会阅读本书
本书假设你已经使用其他编程语言编写过代码,但并不假设你使用了何种语言。我们尝试使材料能广泛的适用于来自很多不同编程背景的开发者。我们不会花费很多时间讨论编程 **是** 什么或者如何理解它。如果编程对于你来说是完全陌生的,你最好先阅读专门介绍编程的数据。
## 如何阅读本书
总体来说,本书假设你会从头到尾顺序阅读。稍后的章节建立在之前章节概念的基础上,同时之前的章节可能不会深入挖掘主题的细节;通常稍后的章节会重新提到这些主题。
你会在本书中发现两类章节:概念章节和项目章节。在项目章节中,我们学习 Rust 的某个方面。在项目章节中,我们应用目前所学的知识一同构建小的程序。第二、十二和二十章是项目章节;其余则是概念章节。
另外,第二章是一个 Rust 语言的介绍实践。我们会在高层次介绍一些概念,并在稍后的章节提供额外的细节。如果你希望立刻就动手实践一下,第二章正好适合你。开始阅读时,你甚至可能希望略过第三章,它介绍了 Rust 中类似其他编程语言中的功能,并直接阅读第四章学习 Rust 的所有权系统。然而,如果你是特别重视细节的学习者,并倾向于在继续之前学习每一个细节,你可能希望略过第二张并直接阅读第三章,并在想要构建项目来实践这些细节时再回到第二章。
第五章讨论了结构体和方法,第六章涉及了枚举、`match` 表达式和 `if let` 控制流结构。你会使用结构体和枚举在 Rust 中创建自定义类型。
第七章会学习 Rust 的模块系统和私有性规则来组织代码和公有应用程序设计接口Application Programming Interface, API。第八章讨论了一些标准库提供的通用集合数据结构比如 vector、字符串和哈希 map。第九章探索了 Rust 的错误处理哲学和技术。
第十章深入理解泛型、trait 和生命周期,他们提供了定义可适用于多种类型的代码的能力。第十一章全部介绍测试,这即便在有 Rust 的安全保证来确保程序逻辑正确时仍然是必要的。第十二章,我们构建了属于自己的在文件中搜索文本的命令行工具 `grep` 的子集功能实现。为此会利用之前章节讨论的很多概念。
第十三章探索了闭包和迭代器Rust 中来自函数式编程语言的功能。第十四章会更深层次的理解 Cargo 并讨论向他人分享库的最佳实践。
第十六章会学习不同的并发编程模型并讨论 Rust 如何帮助你无畏的多线程开发。第十七章着眼于比较 Rust 风格与你可能熟悉的面向对象编程原则。
第十八章是一个模式与模式匹配的参考章节,他们是在整个 Rust 程序中表达观念的强大方式。第十九章包含一个有趣的高级主题的大杂烩,包括不安全 Rust 和更多关于生命周期、 trait、类型、函数和闭包的内容。
第二十章会完成一个实现了底层多线程 web server 的项目!
最后是一些附录,包含了一些关于语言的参考风格格式的实用信息。附录 A 涉及了 Rust 的关键字。附录 B 涉及 Rust 的运算符和符号。附录 C 涉及标准库提供的派生 trait。附录 D 设计宏。
怎样阅读本书都不会有任何问题:如果你希望略过一些内容,请继续!如果你发现疑惑可能会再跳回之前的章节。无论怎样都是可以的。
学习 Rust 的过程中一个重要的部分是学习如何阅读编译器提供的错误信息:它们会指导你编写代码。为此,我们会提供很多不能编译代码示例,以及各个情况下编译器会展示错误信息。请注意如果随便输入并运行随机的示例代码,它们可能无法编译!请确保阅读任何你尝试运行的示例周围的内容检视他们是否有意为错误的。在大部分情况,我们会指引你到达任何不能编译的代码的正确版本。
## 源代码
生成本书的源码可以在 [GitHub][book] 上找到。
[book]: https://github.com/rust-lang/book/tree/master/second-edition/src
> 译者注:本译本的 [GitHub 仓库][trpl-zh-cn],欢迎 Issue 和 PR :)
[trpl-zh-cn]: https://github.com/KaiserY/trpl-zh-cn

@ -0,0 +1,11 @@
# 入门指南
> [ch01-00-getting-started.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch01-00-getting-started.md)
> <br>
> commit 2a5eaaa3566244a37516b8067970ba1f0d561661
让我们开始 Rust 之旅!在本章中,我们会讨论:
* 在 Linux、macOS 和 Windows 上安装 Rust
* 编写一个打印 “Hello, world!” 的程序
* 使用 Rust 的包管理器和构建系统,`cargo`

@ -0,0 +1 @@
# Hello, Cargo!

@ -150,7 +150,7 @@ io::stdin().read_line(&mut guess)
.expect("Failed to read line"); .expect("Failed to read line");
``` ```
如果程序的开头没有 `use std::io` 这一行,可以把函数调用写成 `std::io::stdin`。`stdin` 函数返回一个 [`std::io::stdin`][iostdin]<!-- ignore --> 的实例,这代表终端标准输入句柄的类型。 如果程序的开头没有 `use std::io` 这一行,可以把函数调用写成 `std::io::stdin`。`stdin` 函数返回一个 [`std::io::Stdin`][iostdin]<!-- ignore --> 的实例,这代表终端标准输入句柄的类型。
[iostdin]: https://doc.rust-lang.org/std/io/struct.Stdin.html [iostdin]: https://doc.rust-lang.org/std/io/struct.Stdin.html

@ -59,7 +59,7 @@ RefCell<T> is, perhaps a succinct round up would help? -->
- `Box<T>` 允许在编译时执行不可变(或可变)借用检查;`Rc<T>`仅允许在编译时执行不可变借用检查;`RefCell<T>` 允许在运行时执行不可变(或可变)借用检查。 - `Box<T>` 允许在编译时执行不可变(或可变)借用检查;`Rc<T>`仅允许在编译时执行不可变借用检查;`RefCell<T>` 允许在运行时执行不可变(或可变)借用检查。
- 因为 `RefCell<T>` 允许在运行时执行可变借用检查,所以我们可以在即便 `RefCell<T>` 自身是不可变的情况下修改其内部的值。 - 因为 `RefCell<T>` 允许在运行时执行可变借用检查,所以我们可以在即便 `RefCell<T>` 自身是不可变的情况下修改其内部的值。
一个理由便是指 **内部可变性** 模式。让我们看看何时内部可变性是有用的,并讨论这是如何成为可能的。 一个理由便是指 **内部可变性** 模式。让我们看看何时内部可变性是有用的,并讨论这是如何成为可能的。
### 内部可变性:不可变值的可变借用 ### 内部可变性:不可变值的可变借用

@ -243,7 +243,7 @@ fn main() {
为了使子结点知道其父结点,需要在 `Node` 结构体定义中增加一个 `parent` 字段。问题是 `parent` 的类型应该是什么。我们知道其不能包含 `Rc<T>`,因为这样 `leaf.parent` 将会指向 `branch``branch.children` 会包含 `leaf` 的指针,这会形成引用循环,会造成其 `strong_count` 永远也不会为 0. 为了使子结点知道其父结点,需要在 `Node` 结构体定义中增加一个 `parent` 字段。问题是 `parent` 的类型应该是什么。我们知道其不能包含 `Rc<T>`,因为这样 `leaf.parent` 将会指向 `branch``branch.children` 会包含 `leaf` 的指针,这会形成引用循环,会造成其 `strong_count` 永远也不会为 0.
现在换一种方式思考这个关系,父结点应该拥有其子结点:如果父结点被丢弃了,其子结点也应该丢弃。然而子结点不应该拥有其父结点:如果丢弃子结点,其父结点应该依然存在。这正是弱引用的例子! 现在换一种方式思考这个关系,父结点应该拥有其子结点:如果父结点被丢弃了,其子结点也应该丢弃。然而子结点不应该拥有其父结点:如果丢弃子结点,其父结点应该依然存在。这正是弱引用的例子!
所以 `parent` 使用 `Weak<T>` 类型而不是 `Rc`,具体来说是 `RefCell<Weak<Node>>`。现在 `Node` 结构体定义看起来像这样: 所以 `parent` 使用 `Weak<T>` 类型而不是 `Rc`,具体来说是 `RefCell<Weak<Node>>`。现在 `Node` 结构体定义看起来像这样:
@ -423,7 +423,7 @@ like that to the start of the Weak section? -->
这一章涵盖了如何使用智能指针来做出不同于 Rust 常规引用默认所提供的保证与取舍。`Box<T>` 有一个已知的大小并指向分配在堆上的数据。`Rc<T>` 记录了堆上数据的引用数量以便可以拥有多个所有者。`RefCell<T>` 和其内部可变性提供了一个可以用于当需要不可变类型但是需要改变其内部值能力的类型,并在运行时而不是编译时检查借用规则。 这一章涵盖了如何使用智能指针来做出不同于 Rust 常规引用默认所提供的保证与取舍。`Box<T>` 有一个已知的大小并指向分配在堆上的数据。`Rc<T>` 记录了堆上数据的引用数量以便可以拥有多个所有者。`RefCell<T>` 和其内部可变性提供了一个可以用于当需要不可变类型但是需要改变其内部值能力的类型,并在运行时而不是编译时检查借用规则。
我们还介绍了提供了很多智能指针功能的 trait `Deref``Drop`。同时探索了会造成内存泄露的引用虚幻,以及如何使用 `Weak<T>` 来避免它们。 我们还介绍了提供了很多智能指针功能的 trait `Deref``Drop`。同时探索了会造成内存泄露的引用循环,以及如何使用 `Weak<T>` 来避免它们。
如果本章内容引起了你的兴趣并希望现在就实现你自己的智能指针的话,请阅读 [“The Nomicon”] 来获取更多有用的信息。 如果本章内容引起了你的兴趣并希望现在就实现你自己的智能指针的话,请阅读 [“The Nomicon”] 来获取更多有用的信息。

@ -6,7 +6,7 @@
安全并高效的处理并发编程是 Rust 的另一个主要目标。**并发编程***Concurrent programming*),代表程序的不同部分相互独立的执行,而 **并行编程***parallel programming*代表程序不同部分于同时执行这两个概念随着计算机越来越多的利用多处理器的优势时显得愈发重要。由于历史原因在此类上下文中编程一直是困难且容易出错的Rust 希望能改变这一点。 安全并高效的处理并发编程是 Rust 的另一个主要目标。**并发编程***Concurrent programming*),代表程序的不同部分相互独立的执行,而 **并行编程***parallel programming*代表程序不同部分于同时执行这两个概念随着计算机越来越多的利用多处理器的优势时显得愈发重要。由于历史原因在此类上下文中编程一直是困难且容易出错的Rust 希望能改变这一点。
起初Rust 团队认为确保内存安全和防止并发问题是两个分别需要不同方法应对的挑战。随着时间的推移,团队发现所有权和类型系统是一系列解决内存安全 **和** 并发问题的强力的工具通过改进所有权和类型检查Rust 很多并发错误都是 **编译时** 错误,而非运行时错误。因此,相比花费大量时间尝试重现运行时并发 bug 出现的特定情况Rust 会拒绝编译不正确的代码并提供解释问题的错误信息。因此,你可以在开发时而不是不慎部署到生产环境后修复代码。我们给 Rust 的这一部分起了一个绰号 **无畏并发***fearless concurrency*)。无畏并发令你的代码免于出现诡异的 bug 并可以轻松重构且无需担心会引入新的 bug。 起初Rust 团队认为确保内存安全和防止并发问题是两个分别需要不同方法应对的挑战。随着时间的推移,团队发现所有权和类型系统是一系列解决内存安全 **和** 并发问题的强力的工具通过改进所有权和类型检查Rust 很多并发错误都是 **编译时** 错误,而非运行时错误。因此,相比花费大量时间尝试重现运行时并发 bug 出现的特定情况Rust 会拒绝编译不正确的代码并提供解释问题的错误信息。因此,你可以在开发时而不是不慎部署到生产环境后修复代码。我们给 Rust 的这一部分起了一个绰号 **无畏并发***fearless concurrency*)。无畏并发令你的代码免于出现诡异的 bug 并可以轻松重构且无需担心会引入新的 bug。
> 注意:出于简洁的考虑,我们将很多问题归为并发,而不是更准确的区分并发和(或)并行。如果这是一本专注于并发和/或并行的书,我们肯定会更加精确的。对于本章,当我们谈到并发时,请自行脑内替换为并发和(或)并行。 > 注意:出于简洁的考虑,我们将很多问题归为并发,而不是更准确的区分并发和(或)并行。如果这是一本专注于并发和/或并行的书,我们肯定会更加精确的。对于本章,当我们谈到并发时,请自行脑内替换为并发和(或)并行。

@ -20,7 +20,7 @@ Rust 尝试缓和使用线程的负面影响。不过在多线程上下文中编
每一个模型都有其优势和取舍。对于 Rust 来说最重要的取舍是运行时支持。运行时是一个令人迷惑的概念,其在不同上下文中可能有不同的含义。 每一个模型都有其优势和取舍。对于 Rust 来说最重要的取舍是运行时支持。运行时是一个令人迷惑的概念,其在不同上下文中可能有不同的含义。
在当前上下文中,**运行时** 代表进制文件中包含的由语言自身提供的代码。这些代码根据语言的不同可大可小,不过任何非汇编语言都会有一定数量的运行时代码。为此,通常人们说一个语言 “没有运行时”,一般意味着 “小运行时”。更小的运行时拥有更少的功能不过其优势在于更小的二进制输出,这使其易于在更多上下文中与其他语言结合。虽然很多语言觉得增加运行时来换取更多功能没有什么问题,但是 Rust 需要做到几乎没有运行时,同时为了保持高性能必需能够调用 C 语言,这点也是不能妥协的。 在当前上下文中,**运行时** 代表进制文件中包含的由语言自身提供的代码。这些代码根据语言的不同可大可小,不过任何非汇编语言都会有一定数量的运行时代码。为此,通常人们说一个语言 “没有运行时”,一般意味着 “小运行时”。更小的运行时拥有更少的功能不过其优势在于更小的二进制输出,这使其易于在更多上下文中与其他语言结合。虽然很多语言觉得增加运行时来换取更多功能没有什么问题,但是 Rust 需要做到几乎没有运行时,同时为了保持高性能必需能够调用 C 语言,这点也是不能妥协的。
绿色线程的 M:N 模型更大的语言运行时来管理这些线程。为此Rust 标准库只提供了 1:1 线程模型实现。因为 Rust 是如此底层的语言,所以有相应的 crate 实现了 M:N 线程模型,如果你宁愿牺牲性能来换取例如更好的线程运行控制和更低的上下文切换成本。 绿色线程的 M:N 模型更大的语言运行时来管理这些线程。为此Rust 标准库只提供了 1:1 线程模型实现。因为 Rust 是如此底层的语言,所以有相应的 crate 实现了 M:N 线程模型,如果你宁愿牺牲性能来换取例如更好的线程运行控制和更低的上下文切换成本。

@ -58,7 +58,7 @@ fn main() {
让我们看看当 `match` 语句运行的时候发生了什么。第一个匹配分支的模式并不匹配 `x` 中定义的值,所以继续。 让我们看看当 `match` 语句运行的时候发生了什么。第一个匹配分支的模式并不匹配 `x` 中定义的值,所以继续。
第二个匹配分支中的模式引入了一个新变量 `y`,它会匹配任何 `Some` 中的值。因为我们在 `match` 表达式的新作用域中,这是一个新变量,而不是开头声明为值 10 的那个 `y`。这个新的 `y` 绑定会撇配任何 `Some` 中的值,在这是`x` 中的值。因此这个 `y` 绑定了 `x``Some` 内部的值。这个值是 5所以这个分支的表达式将会执行并打印出 `Matched, y = 5` 第二个匹配分支中的模式引入了一个新变量 `y`,它会匹配任何 `Some` 中的值。因为我们在 `match` 表达式的新作用域中,这是一个新变量,而不是开头声明为值 10 的那个 `y`。这个新的 `y` 绑定会匹配任何 `Some` 中的值,在这里`x` 中的值。因此这个 `y` 绑定了 `x``Some` 内部的值。这个值是 5所以这个分支的表达式将会执行并打印出 `Matched, y = 5`
<!-- Below -- We haven't fully introduced the underscore yet, is there anything <!-- Below -- We haven't fully introduced the underscore yet, is there anything
else we could use for that final arm? --> else we could use for that final arm? -->
@ -238,7 +238,7 @@ fn main() {
#### 解构枚举 #### 解构枚举
本书之前的部分曾经解构过么局,比如第六章中示例 6-5 中解构了一个 `Option<i32>`。一个当时没有明确提到的细节是解构枚举的模式需要对应枚举所定义的储存数据的方式。让我们以示例 6-2 中的 `Message` 枚举为例,编写一个 `match` 使用模式解构每一个内部值,如示例 18-15 所示: 本书之前的部分曾经解构过枚举,比如第六章中示例 6-5 中解构了一个 `Option<i32>`。一个当时没有明确提到的细节是解构枚举的模式需要对应枚举所定义的储存数据的方式。让我们以示例 6-2 中的 `Message` 枚举为例,编写一个 `match` 使用模式解构每一个内部值,如示例 18-15 所示:
<span class="filename">文件名: src/main.rs</span> <span class="filename">文件名: src/main.rs</span>

@ -356,4 +356,4 @@ unsafe impl Foo for i32 {
### 何时使用不安全代码 ### 何时使用不安全代码
使用 `unsafe` 来进行这四个操作之一是没有问题的,甚至是不需要深思熟虑的,不过使得 `unsafe` 代码正确也实属不易因为编译器不能帮助保证内存安全。当有理由使用 `unsafe` 代码时,是可以么做的,通过使用显式的 `unsafe` 标注使得在出现错误时易于追踪问题的源头。 使用 `unsafe` 来进行这四个操作之一是没有问题的,甚至是不需要深思熟虑的,不过使得 `unsafe` 代码正确也实属不易因为编译器不能帮助保证内存安全。当有理由使用 `unsafe` 代码时,是可以么做的,通过使用显式的 `unsafe` 标注使得在出现错误时易于追踪问题的源头。

@ -218,7 +218,7 @@ Rust 需要知道应该为特定类型的值分配多少内存,同时所有同
所以虽然 `&T` 是一个储存了 `T` 所在的内存位置的单个值,`&str` 则是 **两个** 值:`str` 的地址和其长度。这样,`&str` 就有了一个在编译时可以知道的大小:它是 `usize` 长度的两倍。也就是说,我们总是知道 `&str` 的大小,而无论其引用的字符串是多长。这里是 Rust 中动态大小类型的常规用法:他们有一些额外的元信息来储存动态信息的大小。这引出了动态大小类型的黄金规则:必须将动态大小类型的值置于某种指针之后。 所以虽然 `&T` 是一个储存了 `T` 所在的内存位置的单个值,`&str` 则是 **两个** 值:`str` 的地址和其长度。这样,`&str` 就有了一个在编译时可以知道的大小:它是 `usize` 长度的两倍。也就是说,我们总是知道 `&str` 的大小,而无论其引用的字符串是多长。这里是 Rust 中动态大小类型的常规用法:他们有一些额外的元信息来储存动态信息的大小。这引出了动态大小类型的黄金规则:必须将动态大小类型的值置于某种指针之后。
可以将 `str` 与所有类型的指针结合:比如 `Box<str>``Rc<str>`。事实上之前我们已经见过了不过是另一个动态大小类型trait。每一个 trait 都是一个可以通过 trait 名称来引用的动态大小类型。在第十七章 “为使用不同类型的值而设计的 trait 对象” 部分,我们提到了为了将 trait 用于 trait 对象,必须将他们放入指针之后,比如 `&Trait``Box<Trait>``Rc<Trait>` 也可以。trait 之所以是动态大小类型的原因是必须这样才能这样使用它。 可以将 `str` 与所有类型的指针结合:比如 `Box<str>``Rc<str>`。事实上之前我们已经见过了不过是另一个动态大小类型trait。每一个 trait 都是一个可以通过 trait 名称来引用的动态大小类型。在第十七章 “为使用不同类型的值而设计的 trait 对象” 部分,我们提到了为了将 trait 用于 trait 对象,必须将他们放入指针之后,比如 `&Trait``Box<Trait>``Rc<Trait>` 也可以。trait 之所以是动态大小类型的是因为只有这样才能使用它。
#### `Sized` trait #### `Sized` trait

@ -0,0 +1,19 @@
# 前言
> [foreword.md](https://github.com/rust-lang/book/blob/master/second-edition/src/foreword.md)
> <br>
> commit 5e085bd1add34aec03416e891751552b439dde52
事物并非总是简单明了Rust 程序设计语言的本质在于 **授权***empowerment*无论你现在编写的是何种代码Rust 能授权你在更为广泛的编程领域走得更远,写出自信。
举例来说“系统层面”“systems-level”处理内存管理、数据表示和并发的底层细节。这个编程领域被视为神秘的传统只为数年专注学习所挑选出的少数人所触及也只有他们能避免其恶名昭著的缺陷。即是谨慎的实践者亦唯恐代码被利用、崩溃或损坏。
Rust 打破了这些障碍,其消除了旧的缺陷并提供了伴你一路同行的友好、精良的工具。想要 “深入” 底层控制的程序员可以使用 Rust无需冒着常见的崩溃或安全漏洞的风险也无需学习时常改变的工具链的最新知识。其语言本身更是被设计为自然而然的引导你编写出在运行速度和内存使用上都十分高效的可靠代码。
已经在从事编写底层代码的程序员可以使用 Rust 来提升抱负。例如,在 Rust 中引入并行是相对较为低风险的操作:编译器会为你捕获经典的错误。同时你可以自信的采取更为激进的优化,而不会意外引入崩溃或漏洞。
另一方面 Rust 并不局限于底层系统编程。其表现力与工程学足以愉快的编写 CLI 应用、web server 和很多其他类型的代码 —— 在本书之后你会找到所有这些场景的简单示例。使用 Rust 你学习的技能可以从一个领域延伸到另一个领域;你可以学习 Rust 来编写 web 应用,接着将同样的技能应用到你的 Raspberry Pi 上。
本书全面拥抱 Rust 授权于用户的潜力。其内容平易近人,致力于帮助你不仅仅提升 Rust 的知识,并且提升你作为程序员整体的理解与自信。那么让我们准备好深入学习 Rust吧打开新世界的大门 :) —— 欢迎加入 Rust 社区!
— Nicholas Matsakis 和 Aaron Turon
Loading…
Cancel
Save