Merge pull request #476 from AllanDowney/patch-3

Update appendix
pull/479/head
Sunface 3 years ago committed by GitHub
commit 781c05f1d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,4 @@
## 附录 D可派生的 trait
## 附录 D派生特征 derive
在本书的各个部分中,我们讨论了可应用于结构体和枚举定义的 `derive` 属性。被 `derive` 标记的对象会自动实现对应的默认特征代码,继承相应的功能。

@ -1,11 +1,11 @@
# F-难点索引
# 附录 F难点索引
不可否认Rust难点很多而且知识点也很多随着时间的进行或多或少都会对一些难点逐渐模糊这些难点无法通过目录章节名进行索引因此集中放在此附录中进行索引方便读者朋友查阅。
不可否认Rust 难点很多,而且知识点也很多,随着时间的进行,或多或少都会对一些难点逐渐模糊,这些难点无法通过目录章节名进行索引,因此集中放在此附录中,进行索引,方便读者朋友查阅。
| 难点及链接 | 简介 |
|----- | ------ |
| [?](../basic/result-error/result.md#传播界的大明星:) | 用于简化错误传播 |
| [()](../basic/base-type/function.md#无返回值) | 单元类型 |
| `!` : [1](../basic/base-type/function.md#永不返回的函数), [2](../advance/custom-type.md#!从不返回类型) | 永不返回 |
| [@](../basic/match-pattern/all-patterns.md#绑定) | 为一个字段绑定另外一个变量 |
| ['a: 'b](../advance/lifetime/advance.md#生命周期约束) | 生命周期约束 |
| [?](https://course.rs/basic/result-error/result.html#传播界的大明星-) | 用于简化错误传播 |
| [()](https://course.rs/basic/base-type/function.html#无返回值) | 单元类型 |
| `!` : [1](https://course.rs/basic/base-type/function.html#永不返回的函数), [2](https://course.rs/advance/into-types/custom-type.html#永不返回类型) | 永不返回 |
| [@](https://course.rs/basic/match-pattern/all-patterns.html#绑定) | 为一个字段绑定另外一个变量 |
| ['a: 'b](https://course.rs/advance/lifetime/advance.html#生命周期约束-hrtb) | 生命周期约束 |

@ -1,6 +1,6 @@
# C-表达式
# 附录 C表达式
在[语句与表达式]章节中,我们对表达式有过介绍,下面对这些常用表达式进行一一说明。
在[语句与表达式](https://course.rs/basic/base-type/statement-expression.html)章节中,我们对表达式有过介绍,下面对这些常用表达式进行一一说明。
### 基本表达式
```rust
@ -8,7 +8,7 @@ let n = 3;
let s = "test";
```
### if表达式
### if 表达式
```rust
fn main() {
let var1 = 10;
@ -23,9 +23,9 @@ fn main() {
}
```
通过`if`表达式将值赋予`var2`.
通过 `if` 表达式将值赋予 `var2`
你还可以在循环中结合`continue`、`break`来使用:`
你还可以在循环中结合 `continue` 、`break` 来使用:
```rust
let mut v = 0;
for i in 1..10 {
@ -35,10 +35,10 @@ for i in 1..10 {
i
}
}
println!("{}",v);
println!("{}", v);
```
### if let表达式
### if let 表达式
```rust
let o = Some(3);
let v = if let Some(x) = o {
@ -48,7 +48,7 @@ let v = if let Some(x) = o {
};
```
### match表达式
### match 表达式
```rust
let o = Some(3);
let v = match o {
@ -57,7 +57,7 @@ let v = match o {
};
```
### loop表达式
### loop 表达式
```rust
let mut n = 0;
let v = loop {
@ -68,7 +68,7 @@ let v = loop {
};
```
### 语句块{}
### 语句块 {}
```rust
let mut n = 0;
let v = {

@ -1,5 +1,5 @@
# 附录
附录中包含了一些Rust常用概念的快速索引方便你的日常查询使用。
附录中包含了一些 Rust 常用概念的快速索引,方便你的日常查询使用。
> 大部分的附录借鉴了Rust Book以及相应的[中文翻译书籍](https://rustwiki.org/zh-CN/book/),但同时做了一些的修改,增加准确性和阅读流畅度
> 大部分的附录借鉴了 Rust Book 以及相应的 [中文翻译书籍](https://rustwiki.org/zh-CN/book/),但同时做了一些的修改,增加准确性和阅读流畅度

@ -102,4 +102,4 @@ fn main() {
此代码编译没有任何错误。注意 `r#` 前缀需同时用于函数名定义和 `main` 函数中的调用。
原生标识符允许使用你选择的任何单词作为标识符,即使该单词恰好是保留关键字。 此外原生标识符允许你使用其它Rust版本编写的库。比如`try` 在Rust 2015 edition 中不是关键字却在Rust 2018 edition是关键字。所以如果用2015 edition 编写的库中带有 `try` 函数,在 2018 edition 中调用时就需要使用原始标识符语法,在这里是 `r#try`
原生标识符允许使用你选择的任何单词作为标识符,即使该单词恰好是保留关键字。 此外,原生标识符允许你使用其它 Rust 版本编写的库。比如,`try` 在 Rust 2015 edition 中不是关键字,却在 Rust 2018 edition 是关键字。所以如果用 2015 edition 编写的库中带有 `try` 函数,在 2018 edition 中调用时就需要使用原始标识符语法,在这里是 `r#try`

@ -7,9 +7,9 @@
表 B-1 包含了 Rust 中的运算符、上下文中的示例、简短解释以及该运算符是否可重载。如果一个运算符是可重载的,则该运算符上用于重载的特征也会列出。
下表中,`expr`是表达式,`ident`是标识符,`type`是类型,`var`是变量,`trait`是特征,`pat`是匹配分支(pattern)。
下表中,`expr` 是表达式,`ident` 是标识符,`type` 是类型,`var` 是变量,`trait` 是特征,`pat` 是匹配分支(pattern)。
<span class="caption">表 B-1: 运算符</span>
<span class="caption">表 B-1运算符</span>
| 运算符 | 示例 | 解释 | 是否可重载 |
|----------|---------|-------------|---------------|
@ -87,7 +87,7 @@
| `!` | 代表总是空的类型,用于发散函数(无返回值函数) |
| `_` | 模式绑定中表示忽略的意思;也用于增强整型字面值的可读性 |
表 B-3展示了模块和对象调用路径的语法。
表 B-3 展示了模块和对象调用路径的语法。
<span class="caption">表 B-3路径相关语法</span>
@ -121,7 +121,7 @@
表 B-5 展示了使用特征约束来限制泛型参数的符号。
<span class="caption">表 B-5: 特征约束</span>
<span class="caption">表 B-5特征约束</span>
| 符号 | 解释 |
|--------|-------------|
@ -134,7 +134,7 @@
表 B-6 展示了宏以及在一个对象上定义属性的符号。
<span class="caption">表 B-6: 宏与属性</span>
<span class="caption">表 B-6宏与属性</span>
| 符号 | 解释 |
|--------|-------------|
@ -147,7 +147,7 @@
表 B-7 展示了写注释的符号。
<span class="caption">表 B-7: 注释</span>
<span class="caption">表 B-7注释</span>
| 符号 | 注释 |
|--------|-------------|
@ -160,7 +160,7 @@
表 B-8 展示了出现在使用元组时的符号。
<span class="caption">表 B-8: 元组</span>
<span class="caption">表 B-8元组</span>
| 符号 | 解释 |
|--------|-------------|
@ -175,7 +175,7 @@
表 B-9 展示了使用大括号的上下文。
<span class="caption">表 B-9: 大括号</span>
<span class="caption">表 B-9大括号</span>
| 符号 | 解释 |
|---------|-------------|
@ -184,7 +184,7 @@
表 B-10 展示了使用方括号的上下文。
<span class="caption">表 B-10: 方括号</span>
<span class="caption">表 B-10方括号</span>
| 符号 | 解释 |
|---------|-------------|

@ -1 +1 @@
# E-prelude模块
# 附录 Eprelude 模块

@ -1,45 +1,46 @@
# 附录 GRust版本发布
## Rust版本说明
## Rust 版本说明
早在第一章,我们见过 `cargo new`*Cargo.toml* 中增加了一些有关 `edition` 的元数据。本附录将解释其意义!
与其它语言相比Rust的更新迭代较为频繁(得益于精心设计过的发布流程以及Rust语言开发者团队管理)
- 每6周发布一个迭代版本
- 2-3年发布一个新的大版本Rust 2021 edtion, 每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。
与其它语言相比Rust 的更新迭代较为频繁(得益于精心设计过的发布流程以及 Rust 语言开发者团队管理):
- 每 6 周发布一个迭代版本
- 2 - 3 年发布一个新的大版本:每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。
好处在于,可以满足不同的用户群体的需求:
- 对于活跃的Rust用户他们总是能很快获取到新的语言内容毕竟尝鲜是技术爱好者的共同特点:)
- 对于一般的用户edition的发布会告诉这些用户Rust语言相比上次大版本发布有了重大的改进值得一看
- 对于Rust语言开发者可以让他们的工作成果更快的被世人所知不必锦衣夜行
- 对于活跃的 Rust 用户,他们总是能很快获取到新的语言内容,毕竟,尝鲜是技术爱好者的共同特点:)
- 对于一般的用户edition 的发布会告诉这些用户Rust 语言相比上次大版本发布,有了重大的改进,值得一看
- 对于 Rust 语言开发者,可以让他们的工作成果更快的被世人所知,不必锦衣夜行
在本文档编写时Rust 已经有三个版本Rust 2015、2018、2021。本书基于 Rust 2021 edition 编写。
在本文档编写时Rust 已经有三个版本Rust 2015、2018、2021。本书基于 `Rust 2021 edition` 编写。
*Cargo.toml* 中的 `edition` 字段表明代码应该使用哪个版本编译。如果该字段不存在,其默认为 `2021` 以提供后向兼容性。
每个项目都可以选择不同于默认的 2021 edition 的版本。这样,版本可能会包含不兼容的修改,比如新版本中新增的关键字可能会与老代码中的标识符冲突并导致错误。不过,除非你选择应用这些修改,否则旧代码依然能够被编译,即便你升级了编译器版本。
每个项目都可以选择不同于默认的 `Rust 2021 edition` 的版本。这样,版本可能会包含不兼容的修改,比如新版本中新增的关键字可能会与老代码中的标识符冲突并导致错误。不过,除非你选择应用这些修改,否则旧代码依然能够被编译,即便你升级了编译器版本。
所有 Rust 编译器都支持任何之前存在的编译器版本,并可以链接任何支持版本的包。编译器修改只影响最初的解析代码的过程。因此,如果你使用 Rust 2021 而某个依赖使用 Rust 2018你的项目仍旧能够编译并使用该依赖。反之若项目使用 Rust 2018 而依赖使用 Rust 2021 亦可工作。
所有 Rust 编译器都支持任何之前存在的编译器版本,并可以链接任何支持版本的包。编译器修改只影响最初的解析代码的过程。因此,如果你使用 `Rust 2021` 而某个依赖使用 `Rust 2018`,你的项目仍旧能够编译并使用该依赖。反之,若项目使用 `Rust 2018` 而依赖使用 `Rust 2021` 亦可工作。
有一点需要明确:大部分功能在所有版本中都能使用。开发者使用任何 Rust 版本将能继续接收最新稳定版的改进。然而在一些情况,主要是增加了新关键字的时候,则可能出现了只能用于新版本的功能。只需切换版本即可利用新版本的功能。
请查看 [Edition Guide](https://rust-lang-nursery.github.io/edition-guide/) 了解更多细节,这是一个完全介绍版本的书籍,包括如何通过 `cargo fix` 自动将代码迁移到新版本。
## Rust自身开发流程
## Rust 自身开发流程
本附录介绍 Rust语言自身是如何开发的以及这如何影响作为 Rust 开发者的你。
本附录介绍 Rust 语言自身是如何开发的以及这如何影响作为 Rust 开发者的你。
### 无停滞稳定
作为一个语言Rust **十分** 注重代码的稳定性。我们希望 Rust 成为你代码坚实的基础,假如持续地有东西在变,这个希望就实现不了。但与此同时,如果不能实验新功能的话,在发布之前我们又无法发现其中重大的缺陷,而一旦发布便再也没有修改的机会了。
对于这个问题我们的解决方案被称为 “无停滞稳定”“stability without stagnation”其指导性原则是无需担心升级到最新的稳定版 Rust。每次升级应该是无痛的并应带来新功能更少的 bug 和更快的编译速度。
对于这个问题我们的解决方案被称为 “无停滞稳定”“stability without stagnation”其指导性原则是无需担心升级到最新的稳定版 Rust。每次升级应该是无痛的并应带来新功能更少的 Bug 和更快的编译速度。
### Choo, Choo! ~~ 小火车发布流程启动
开发Rust语言是基于一个**火车时刻表**来进行的所有的开发工作在Master分支上完成但是发布就像火车时刻表一样拥有不同的时间发布采用的软件发布列车模型被用于思科IOS和等其它软件项目。Rust 有三个 **发布通道***release channel*
开发 Rust 语言是基于一个**火车时刻表**来进行的:所有的开发工作在 Master 分支上完成但是发布就像火车时刻表一样拥有不同的时间发布采用的软件发布列车模型被用于思科IOS和等其它软件项目。Rust 有三个 **发布通道***release channel*
* Nightly
* Beta
@ -87,7 +88,7 @@ beta: * - - - - - - - - *
stable: *
```
好的Rust 1.5 发布了!然而,我们忘了些东西:因为又过了 6 周,我们还需发布 **新版** Rust 的 beta 版Rust 1.6。所以从 `beta` 生成 `stable` 分支后,新版的 `beta` 分支也再次从 `nightly` 生成:
好的Rust 1.5 发布了!然而,我们忘了些东西:因为又过了 6 周,我们还需发布 **新版** Rust 的 beta 版Rust 1.6。所以从 `beta` 分支生成 `stable` 分支后,新版的 `beta` 分支也再次从 `nightly` 生成:
```text
nightly: * - - * - - * - - * - - * - - * - * - *
@ -101,7 +102,7 @@ stable: *
Rust 每 6 周发布一个版本,如时钟般准确。如果你知道了某个 Rust 版本的发布时间就可以知道下个版本的时间6 周后。每 6 周发布版本的一个好的方面是下一班车会来得更快。如果特定版本碰巧缺失某个功能也无需担心:另一个版本很快就会到来!这有助于减少因临近发版时间而偷偷释出未经完善的功能的压力。
多亏了这个过程,你总是可以切换到下一版本的 Rust 并验证是否可以轻易的升级:如果 beta 版不能如期工作,你可以向 Rust 团队报告并在发布稳定版之前得到修复beta 版造成的破坏是非常少见的,不过 `rustc` 也不过是一个软件,可能会存在 bug。
多亏了这个过程,你总是可以切换到下一版本的 Rust 并验证是否可以轻易的升级:如果 beta 版不能如期工作,你可以向 Rust 团队报告并在发布稳定版之前得到修复beta 版造成的破坏是非常少见的,不过 `rustc` 也不过是一个软件,可能会存在 Bug。
### 不稳定功能
@ -113,7 +114,7 @@ Rust 每 6 周发布一个版本,如时钟般准确。如果你知道了某个
### Rustup 和 Rust Nightly 的职责
#### 安装Rust Nightly版本
#### 安装 Rust Nightly 版本
Rustup 使得改变不同发布通道的 Rust 更为简单,其在全局或分项目的层次工作。其默认会安装稳定版 Rust。例如为了安装 nightly
```text
@ -137,14 +138,14 @@ $ cd ~/projects/needs-nightly
$ rustup override set nightly
```
现在,每次在 *~/需要nightly的项目/*下(在项目的根目录下也就是Cargo.toml所在的目录) 调用 `rustc``cargo``rustup` 会确保使用 nightly 版 Rust。在你有很多 Rust 项目时大有裨益!
现在,每次在 *~/需要nightly的项目/*下(在项目的根目录下,也就是 `Cargo.toml` 所在的目录) 调用 `rustc``cargo``rustup` 会确保使用 nightly 版 Rust。在你有很多 Rust 项目时大有裨益!
### RFC 过程和团队
那么你如何了解这些新功能呢Rust 开发模式遵循一个 **Request For Comments (RFC) 过程**。如果你希望改进 Rust可以编写一个提议也就是 RFC。
任何人都可以编写 RFC 来改进 Rust同时这些 RFC 会被 Rust 团队评审和讨论,他们由很多不同分工的子团队组成。这里是 [Rust 官网](https://www.rust-lang.org/governance) 所有团队的总列表,其包含了项目中每个领域的团队:语言设计、编译器实现、基础设施、文档等。各个团队会阅读相应的提议和评论,编写回复,并最终达成接受或回绝功能的一致。
任何人都可以编写 RFC 来改进 Rust同时这些 RFC 会被 Rust 团队评审和讨论,他们由很多不同分工的子团队组成。这里是 [Rust 官网](https://www.rust-lang.org/governance) 所有团队的总列表,其包含了项目中每个领域的团队:语言设计、编译器实现、基础设施、文档等。各个团队会阅读相应的提议和评论,编写回复,并最终达成接受或回绝功能的一致。
如果功能被接受了,在 Rust 仓库会打开一个 issue人们就可以实现它。实现功能的人可能不是最初提议功能的人当实现完成后其会合并到 `master` 分支并位于一个特性开关feature gate之后正如 [不稳定功能](#不稳定功能) 部分所讨论的。
如果功能被接受了,在 Rust 仓库会打开一个 issue人们就可以实现它。实现功能的人可能不是最初提议功能的人当实现完成后其会合并到 `master` 分支并位于一个特性开关feature gate之后正如[不稳定功能](#不稳定功能) 部分所讨论的。
在稍后的某个时间,一旦使用 nightly 版的 Rust 团队能够尝试这个功能了,团队成员会讨论这个功能在 nightly 中运行的情况,并决定是否应该进入稳定版。如果决定继续推进,特性开关会移除,然后这个功能就被认为是稳定的了!乘着“发布的列车”,最终在新的稳定版 Rust 中出现。

@ -1,6 +1,6 @@
# Rust新版解读 | 1.58 | 重点: 格式化字符串捕获环境中的值
# Rust 新版解读 | 1.58 | 重点: 格式化字符串捕获环境中的值
众所周知Rust小版本发布非常频繁6周就发布一次因此通常不会有特别值得普通用户关注的内容但是这次1.58版本不同,新增了(stable化了)一个非常好用的功能:在格式化字符串时捕获环境中的值。
众所周知Rust 小版本发布非常频繁6 周就发布一次,因此通常不会有特别值得普通用户关注的内容,但是这次 1.58 版本不同,新增了(stable 化了)一个非常好用的功能: **在格式化字符串时捕获环境中的值**
> Rust 1.58 官方 release doc: [Announcing Rust 1.58.0 | Rust Blog](https://blog.rust-lang.org/2022/01/13/Rust-1.58.0.html)
@ -18,7 +18,7 @@ fn main() {
println!("Hello, {person}!", person = p);
}
```
问题倒也不大但是一旦格式化字符串长了后就会非常冗余而在1.58后,我们可以这么写:
问题倒也不大,但是一旦格式化字符串长了后,就会非常冗余,而在 1.58 后,我们可以这么写:
```rust
fn get_person() -> String {
String::from("sunface")
@ -35,8 +35,9 @@ for (name, score) in get_scores() {
println!("{name}: {score:width$.precision$}");
}
```
但也有局限,它只能捕获普通的变量,对于更复杂的类型(例如表达式),可以先将它赋值给一个变量或使用以前的`name = expression`形式的格式化参数。
目前除了`panic!`外,其它接收格式化参数的宏,都可以使用新的特性。对于`panic!` 而言,如果还在使用`Rust2015`或`2018`大版本 ,那`panic!("{ident}")`依然会被当成 正常的字符串来处理,同时编译器会给予`warn`提示。而对于`2021版本`,则可以正常使用:
但也有局限,它只能捕获普通的变量,对于更复杂的类型(例如表达式),可以先将它赋值给一个变量或使用以前的 `name = expression` 形式的格式化参数。
目前除了 `panic!` 外,其它接收格式化参数的宏,都可以使用新的特性。对于 `panic!` 而言,如果还在使用 `2015版本``2018版本` 版本 ,那 `panic!("{ident}")` 依然会被当成 正常的字符串来处理,同时编译器会给予 `warn` 提示。而对于 `2021版本` ,则可以正常使用:
```rust
fn get_person() -> String {
String::from("sunface")
@ -53,9 +54,9 @@ thread 'main' panicked at 'Hello, sunface!', src/main.rs:6:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
## 比unwrap更危险的unwrap_unchecked
## 比 unwrap 更危险的 unwrap_unchecked
在1.58中为`Option`和`Result`新增了`unwrap_unchecked`方法,与`unwrap`遇到错误或者空值直接`panic`不同,`unwrap_unchecked`遇到错误时处理方式糟糕的多:
1.58 中为 `Option` `Result` 新增了 `unwrap_unchecked` 方法,与 `unwrap` 遇到错误或者空值直接 `panic` 不同,`unwrap_unchecked` 遇到错误时处理方式糟糕的多:
```rust
fn get_num() -> Option<i32> {
None
@ -72,9 +73,9 @@ fn main() {
zsh: segmentation fault cargo run
```
嗯,段错误了,对比下`panic`,有一种泪流满面的冲动:我要这不安全的方法何用?
嗯,段错误了,对比下 `panic`,有一种泪流满面的冲动:我要这不安全的方法何用?
其实,还真有些用:
- 想要较小的可执行文件时(嵌入式wasm等)该方法就可以大显身手。因为panic会导致[二进制可执行文件变大不少](https://zhuanlan.zhihu.com/p/445465092)
- 它还可以提高一点性能, 因为编译器可能无法优化掉unwrap的指令分支 虽然它只会增加区区几条分支预测指令
- 想要较小的可执行文件时嵌入式WASM等该方法就可以大显身手。因为 `panic` 会导致[二进制可执行文件变大不少](https://zhuanlan.zhihu.com/p/445465092)
- 它还可以提高一点性能, 因为编译器可能无法优化掉 `unwrap` 的指令分支, 虽然它只会增加区区几条分支预测指令

@ -1,4 +1,4 @@
# Rust新版解读 | 1.59 | 重点: 内联汇编、解构式赋值
# Rust 新版解读 | 1.59 | 重点: 内联汇编、解构式赋值
Rust 团队于今天凌晨( 2022-02-25 )发布了最新的 1.59 版本,其中最引人瞩目的特性应该就是支持在代码中内联汇编了,一起来看看。
## 内联汇编( inline assembly )
@ -107,9 +107,9 @@ wasm-opt = ['-Os']
[github上一个开源仓库](https://github.com/rsadsb/adsb_deku/blob/master/CHANGELOG.md#unreleased)也证明了这一点,总体来看,这个配置的效果是非常显著的!
## 默认关闭增量编译
1.59.0 版本默认关闭了增量编译的功能(你可以通过环境变量显式地启用:`RUSTC_FORCE_INCREMENTAL=1` )这会降低已知bug [#94124](https://github.com/rust-lang/rust/issues/94124) 的影响,该 bug 会导致增量编译过程中的反序列化的误和 panic
1.59.0 版本默认关闭了增量编译的功能(你可以通过环境变量显式地启用:`RUSTC_FORCE_INCREMENTAL=1` ),这会降低已知 Bug [#94124](https://github.com/rust-lang/rust/issues/94124) 的影响,该 Bug 会导致增量编译过程中的反序列化错误和 `panic`
不过大家也不用担心,这个 bug 会在 1.60.0 版本修复,也就是六周后,增量编译会重新设置为默认开启,如果没有意外的话 :)
不过大家也不用担心,这个 Bug 会在 1.60.0 版本修复,也就是 6 周后,增量编译会重新设置为默认开启,如果没有意外的话 :)
## 稳定化的 API 列表
一些方法和特征实现现在已经可以 stable 中使用,具体见[官方发布说明](https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html#stabilized-apis)

@ -1,2 +1,2 @@
# H-Rust更新版本列表
本目录包含了Rust历次版本更新的重要内容解读需要注意每个版本实际更新的内容要比这里记录的更多全部内容请访问每节开头的官方链接查看。
# 附录 HRust 更新版本列表
本目录包含了 Rust 历次版本更新的重要内容解读,需要注意,每个版本实际更新的内容要比这里记录的更多,全部内容请访问每节开头的官方链接查看。

Loading…
Cancel
Save