fix link for typst

pull/760/head
KaiserY 11 months ago
parent 7309b64c6c
commit 8174380c00

@ -103,7 +103,7 @@
- [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)
## 高级主题 ## 高级主题

@ -103,7 +103,7 @@
- [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)
## 高级主题 ## 高级主题

@ -49,7 +49,7 @@ Linux 用户通常需要根据发行版distribution文档安装 GCC 或 Cl
本书的余下部分会使用能同时运行于 *cmd.exe* 和 PowerShell 的命令。如果存在特定差异,我们会解释使用哪一个。 本书的余下部分会使用能同时运行于 *cmd.exe* 和 PowerShell 的命令。如果存在特定差异,我们会解释使用哪一个。
### 检查安装是否正确Troubleshooting ### 故障排除Troubleshooting
要检查是否正确安装了 Rust打开命令行并输入 要检查是否正确安装了 Rust打开命令行并输入

@ -138,5 +138,5 @@ $ ./main # Windows 是 .\main.exe
仅仅使用 `rustc` 编译简单程序是没问题的,不过随着项目的增长,你可能需要管理你项目的方方面面,并让代码易于分享。接下来,我们要介绍一个叫做 Cargo 的工具,它会帮助你编写真实世界中的 Rust 程序。 仅仅使用 `rustc` 编译简单程序是没问题的,不过随着项目的增长,你可能需要管理你项目的方方面面,并让代码易于分享。接下来,我们要介绍一个叫做 Cargo 的工具,它会帮助你编写真实世界中的 Rust 程序。
[troubleshooting]: ch01-01-installation.html#troubleshooting [troubleshooting]: ch01-01-installation.html#故障排除troubleshooting
[devtools]: appendix-04-useful-development-tools.html [devtools]: appendix-04-useful-development-tools.html

@ -164,7 +164,7 @@ $ cargo build
是时候通过构建更实质性的程序来熟悉读写 Rust 代码了。所以在第二章我们会构建一个猜猜看游戏程序。如果你更愿意从学习 Rust 常用的编程概念开始,请阅读第三章,接着再回到第二章。 是时候通过构建更实质性的程序来熟悉读写 Rust 代码了。所以在第二章我们会构建一个猜猜看游戏程序。如果你更愿意从学习 Rust 常用的编程概念开始,请阅读第三章,接着再回到第二章。
[installation]: ch01-01-installation.html#installation [installation]: ch01-01-installation.html#安装
[toml]: https://toml.io [toml]: https://toml.io
[appendix-e]: appendix-05-editions.html [appendix-e]: appendix-05-editions.html
[cargo]: https://doc.rust-lang.org/cargo/ [cargo]: https://doc.rust-lang.org/cargo/

@ -536,6 +536,6 @@ You win!
[doccargo]: http://doc.crates.io [doccargo]: http://doc.crates.io
[doccratesio]: http://doc.crates.io/crates-io.html [doccratesio]: http://doc.crates.io/crates-io.html
[match]: ch06-02-match.html [match]: ch06-02-match.html
[shadowing]: ch03-01-variables-and-mutability.html#shadowing [shadowing]: ch03-01-variables-and-mutability.html#隐藏
[parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse [parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse
[integers]: ch03-02-data-types.html#integer-types [integers]: ch03-02-data-types.html#整型

@ -119,7 +119,7 @@ Rust 的 `char` 类型是语言中最原生的字母类型。下面是一些声
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs}} {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs}}
``` ```
注意,我们用单引号声明 `char` 字面量而与之相反的是使用双引号声明字符串字面量。Rust 的 `char` 类型的大小为四个字节 (four bytes),并代表了一个 Unicode 标量值Unicode Scalar Value这意味着它可以比 ASCII 表示更多内容。在 Rust 中带变音符号的字母Accented letters中文、日文、韩文等字符emoji绘文字以及零长度的空白字符都是有效的 `char` 值。Unicode 标量值包含从 `U+0000``U+D7FF``U+E000``U+10FFFF` 在内的值。不过,“字符” 并不是一个 Unicode 中的概念,所以人直觉上的 “字符” 可能与 Rust 中的 `char` 并不符合。第八章的 [“使用字符串储 UTF-8 编码的文本”][strings] 中将详细讨论这个主题。 注意,我们用单引号声明 `char` 字面量而与之相反的是使用双引号声明字符串字面量。Rust 的 `char` 类型的大小为四个字节 (four bytes),并代表了一个 Unicode 标量值Unicode Scalar Value这意味着它可以比 ASCII 表示更多内容。在 Rust 中带变音符号的字母Accented letters中文、日文、韩文等字符emoji绘文字以及零长度的空白字符都是有效的 `char` 值。Unicode 标量值包含从 `U+0000``U+D7FF``U+E000``U+10FFFF` 在内的值。不过,“字符” 并不是一个 Unicode 中的概念,所以人直觉上的 “字符” 可能与 Rust 中的 `char` 并不符合。第八章的 [“使用字符串储 UTF-8 编码的文本”][strings] 中将详细讨论这个主题。
### 复合类型 ### 复合类型
@ -230,11 +230,11 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
这是第一个在实战中遇到的 Rust 安全原则的例子。在很多底层语言中并没有进行这类检查这样当提供了一个不正确的索引时就会访问无效的内存。通过立即退出而不是允许内存访问并继续执行Rust 让你避开此类错误。第九章会更详细地讨论 Rust 的错误处理机制,以及如何编写可读性强而又安全的代码,使程序既不会 panic 也不会导致非法内存访问。 这是第一个在实战中遇到的 Rust 安全原则的例子。在很多底层语言中并没有进行这类检查这样当提供了一个不正确的索引时就会访问无效的内存。通过立即退出而不是允许内存访问并继续执行Rust 让你避开此类错误。第九章会更详细地讨论 Rust 的错误处理机制,以及如何编写可读性强而又安全的代码,使程序既不会 panic 也不会导致非法内存访问。
[comparing-the-guess-to-the-secret-number]: [comparing-the-guess-to-the-secret-number]:
ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number ch02-00-guessing-game-tutorial.html#比较猜测的数字和秘密数字
[twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement [twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement
[control-flow]: ch03-05-control-flow.html#控制流 [control-flow]: ch03-05-control-flow.html#控制流
[strings]: ch08-02-strings.html#使用字符串储-utf-8-编码的文本 [strings]: ch08-02-strings.html#使用字符串储-utf-8-编码的文本
[stack-and-heap]: ch04-01-what-is-ownership.html#the-stack-and-the-heap [stack-and-heap]: ch04-01-what-is-ownership.html#栈stack与堆heap
[vectors]: ch08-01-vectors.html [vectors]: ch08-01-vectors.html
[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html [unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html
[wrapping]: https://doc.rust-lang.org/std/num/struct.Wrapping.html [wrapping]: https://doc.rust-lang.org/std/num/struct.Wrapping.html

@ -119,7 +119,7 @@ let slice = &s[0..len];
let slice = &s[..]; let slice = &s[..];
``` ```
> 注意:字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内,如果尝试从一个多字节字符的中间位置创建字符串 slice则程序将会因错误而退出。出于介绍字符串 slice 的目的,本部分假设只使用 ASCII 字符集;第八章的 [“使用字符串储 UTF-8 编码的文本”][strings] 部分会更加全面的讨论 UTF-8 处理问题。 > 注意:字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内,如果尝试从一个多字节字符的中间位置创建字符串 slice则程序将会因错误而退出。出于介绍字符串 slice 的目的,本部分假设只使用 ASCII 字符集;第八章的 [“使用字符串储 UTF-8 编码的文本”][strings] 部分会更加全面的讨论 UTF-8 处理问题。
在记住所有这些知识后,让我们重写 `first_word` 来返回一个 slice。“字符串 slice” 的类型声明写作 `&str` 在记住所有这些知识后,让我们重写 `first_word` 来返回一个 slice。“字符串 slice” 的类型声明写作 `&str`
@ -219,5 +219,5 @@ assert_eq!(slice, &[2, 3]);
[ch13]: ch13-02-iterators.html [ch13]: ch13-02-iterators.html
[ch6]: ch06-02-match.html#绑定值的模式 [ch6]: ch06-02-match.html#绑定值的模式
[strings]: ch08-02-strings.html#使用字符串储-utf-8-编码的文本 [strings]: ch08-02-strings.html#使用字符串储-utf-8-编码的文本
[deref-coercions]: ch15-02-deref.html#函数和方法的隐式-deref-强制转换 [deref-coercions]: ch15-02-deref.html#函数和方法的隐式-deref-强制转换

@ -136,5 +136,5 @@ Can rect1 hold rect3? false
[enums]: ch06-00-enums.html [enums]: ch06-00-enums.html
[trait-objects]: ch17-02-trait-objects.html [trait-objects]: ch17-02-trait-objects.html
[public]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword [public]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#使用-pub-关键字暴露路径
[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html [modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html

@ -190,6 +190,6 @@ use std::collections::*;
glob 运算符经常用于测试模块 `tests` 中,这时会将所有内容引入作用域;我们将在第十一章 “如何编写测试” 部分讲解。glob 运算符有时也用于 prelude 模式;查看 [标准库中的文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes) 了解这个模式的更多细节。 glob 运算符经常用于测试模块 `tests` 中,这时会将所有内容引入作用域;我们将在第十一章 “如何编写测试” 部分讲解。glob 运算符有时也用于 prelude 模式;查看 [标准库中的文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes) 了解这个模式的更多细节。
[ch14-pub-use]: ch14-02-publishing-to-crates-io.html#exporting-a-convenient-public-api-with-pub-use [ch14-pub-use]: ch14-02-publishing-to-crates-io.html#使用-pub-use-导出合适的公有-api
[rand]: ch02-00-guessing-game-tutorial.html#生成一个随机数 [rand]: ch02-00-guessing-game-tutorial.html#生成一个随机数
[writing-tests]: ch11-01-writing-tests.html#如何编写测试 [writing-tests]: ch11-01-writing-tests.html#如何编写测试

@ -141,4 +141,4 @@ Rust 在编译时就必须准确的知道 vector 中类型的原因在于它需
[data-types]: ch03-02-data-types.html#数据类型 [data-types]: ch03-02-data-types.html#数据类型
[nomicon]: https://doc.rust-lang.org/nomicon/vec/vec.html [nomicon]: https://doc.rust-lang.org/nomicon/vec/vec.html
[vec-api]: https://doc.rust-lang.org/std/vec/struct.Vec.html [vec-api]: https://doc.rust-lang.org/std/vec/struct.Vec.html
[deref]: ch15-02-deref.html#通过解引用运算符追踪指针的值 [deref]: ch15-02-deref.html#追踪指针的值

@ -61,7 +61,7 @@ Blue: 10
`insert` 调用将 `field_name``field_value` 移动到哈希 map 中后,将不能使用这两个绑定。 `insert` 调用将 `field_name``field_value` 移动到哈希 map 中后,将不能使用这两个绑定。
如果将值的引用插入哈希 map这些值本身将不会被移动进哈希 map。但是这些引用指向的值必须至少在哈希 map 有效时也是有效的。第十章 [“生命周期与引用有效性”][validating-references-with-lifetimes] 部分将会更多的讨论这个问题。 如果将值的引用插入哈希 map这些值本身将不会被移动进哈希 map。但是这些引用指向的值必须至少在哈希 map 有效时也是有效的。第十章 [“生命周期确保引用有效”][validating-references-with-lifetimes] 部分将会更多的讨论这个问题。
### 更新哈希 map ### 更新哈希 map
@ -131,5 +131,5 @@ vector、字符串和哈希 map 会在你的程序需要储存、访问和修改
[iterators]: ch13-02-iterators.html [iterators]: ch13-02-iterators.html
[validating-references-with-lifetimes]: [validating-references-with-lifetimes]:
ch10-03-lifetime-syntax.html#生命周期与引用有效性 ch10-03-lifetime-syntax.html#生命周期确保引用有效
[access]: #访问哈希-map-中的值 [access]: #访问哈希-map-中的值

@ -91,4 +91,4 @@ note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose bac
本章后面的小节 [“要不要 panic!”][to-panic-or-not-to-panic] 会再次回到 `panic!` 并讲解何时应该、何时不应该使用 `panic!` 来处理错误情况。接下来,我们来看看如何使用 `Result` 来从错误中恢复。 本章后面的小节 [“要不要 panic!”][to-panic-or-not-to-panic] 会再次回到 `panic!` 并讲解何时应该、何时不应该使用 `panic!` 来处理错误情况。接下来,我们来看看如何使用 `Result` 来从错误中恢复。
[to-panic-or-not-to-panic]: [to-panic-or-not-to-panic]:
ch09-03-to-panic-or-not-to-panic.html#panic-还是不-panic ch09-03-to-panic-or-not-to-panic.html#要不要-panic

@ -248,7 +248,7 @@ src/libcore/result.rs:906:4
<span class="caption">示例 9-12: 修改 `main` 返回 `Result<(), E>` 允许对 `Result` 值使用 `?` 运算符</span> <span class="caption">示例 9-12: 修改 `main` 返回 `Result<(), E>` 允许对 `Result` 值使用 `?` 运算符</span>
`Box<dyn Error>` 类型是一个 **trait 对象***trait object*)第十七章 [“为使用不同类型的值而设计的 trait 对象”][trait-objects] 部分会做介绍。目前可以将 `Box<dyn Error>` 理解为 “任何类型的错误”。在返回 `Box<dyn Error>` 错误类型 `main` 函数中对 `Result` 使用 `?` 是允许的,因为它允许任何 `Err` 值提前返回。即便 `main` 函数体从来只会返回 `std::io::Error` 错误类型,通过指定 `Box<dyn Error>`,这个签名也仍是正确的,甚至当 `main` 函数体中增加更多返回其他错误类型的代码时也是如此。 `Box<dyn Error>` 类型是一个 **trait 对象***trait object*)第十七章 [顾及不同类型值的 trait 对象”][trait-objects] 部分会做介绍。目前可以将 `Box<dyn Error>` 理解为 “任何类型的错误”。在返回 `Box<dyn Error>` 错误类型 `main` 函数中对 `Result` 使用 `?` 是允许的,因为它允许任何 `Err` 值提前返回。即便 `main` 函数体从来只会返回 `std::io::Error` 错误类型,通过指定 `Box<dyn Error>`,这个签名也仍是正确的,甚至当 `main` 函数体中增加更多返回其他错误类型的代码时也是如此。
`main` 函数返回 `Result<(), E>`,如果 `main` 返回 `Ok(())` 可执行程序会以 `0` 值退出,而如果 `main` 返回 `Err` 值则会以非零值退出;成功退出的程序会返回整数 `0`,运行错误的程序会返回非 `0` 的整数。Rust 也会从二进制程序中返回与这个惯例相兼容的整数。 `main` 函数返回 `Result<(), E>`,如果 `main` 返回 `Ok(())` 可执行程序会以 `0` 值退出,而如果 `main` 返回 `Err` 值则会以非零值退出;成功退出的程序会返回整数 `0`,运行错误的程序会返回非 `0` 的整数。Rust 也会从二进制程序中返回与这个惯例相兼容的整数。
@ -257,5 +257,5 @@ src/libcore/result.rs:906:4
现在我们讨论过了调用 `panic!` 或返回 `Result` 的细节,是时候回到它们各自适合哪些场景的话题了。 现在我们讨论过了调用 `panic!` 或返回 `Result` 的细节,是时候回到它们各自适合哪些场景的话题了。
[handle_failure]: ch02-00-guessing-game-tutorial.html#使用-result-类型来处理潜在的错误 [handle_failure]: ch02-00-guessing-game-tutorial.html#使用-result-类型来处理潜在的错误
[trait-objects]: ch17-02-trait-objects.html#为使用不同类型的值而设计的-trait-对象 [trait-objects]: ch17-02-trait-objects.html#顾及不同类型值的-trait-对象
[termination]: https://doc.rust-lang.org/std/process/trait.Termination.html [termination]: https://doc.rust-lang.org/std/process/trait.Termination.html

@ -4,7 +4,7 @@
> <br> > <br>
> commit 92bfbfacf88ee9a814cea0a58e9c019c529ef4ae > commit 92bfbfacf88ee9a814cea0a58e9c019c529ef4ae
*trait* 定义了某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共享的行为。可以使用 *trait bounds* 指定泛型是任何拥有特定行为的类型。 *trait* 定义了某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共行为。可以使用 *trait bounds* 指定泛型是任何拥有特定行为的类型。
> 注意:*trait* 类似于其他语言中的常被称为 **接口***interfaces*)的功能,虽然有一些不同。 > 注意:*trait* 类似于其他语言中的常被称为 **接口***interfaces*)的功能,虽然有一些不同。
@ -190,7 +190,7 @@ fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/src/lib.rs:here}} {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/src/lib.rs:here}}
``` ```
这里尝试返回 `NewsArticle``Tweet`。这不能编译,因为 `impl Trait` 工作方式的限制。第十七章的 [“为使用不同类型的值而设计的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分会介绍如何编写这样一个函数。 这里尝试返回 `NewsArticle``Tweet`。这不能编译,因为 `impl Trait` 工作方式的限制。第十七章的 [顾及不同类型值的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分会介绍如何编写这样一个函数。
### 使用 trait bound 有条件地实现方法 ### 使用 trait bound 有条件地实现方法
@ -221,5 +221,5 @@ blanket implementation 会出现在 trait 文档的 “Implementers” 部分。
trait 和 trait bound 让我们能够使用泛型类型参数来减少重复,而且能够向编译器明确指定泛型类型需要拥有哪些行为。然后编译器可以利用 trait bound 信息检查代码中所用到的具体类型是否提供了正确的行为。在动态类型语言中如果我们调用了一个未定义的方法会在运行时出现错误。Rust 将这些错误移动到了编译时,甚至在代码能够运行之前就强迫我们修复问题。另外,我们也无需编写运行时检查行为的代码,因为在编译时就已经检查过了。这样既提升了性能又不必放弃泛型的灵活性。 trait 和 trait bound 让我们能够使用泛型类型参数来减少重复,而且能够向编译器明确指定泛型类型需要拥有哪些行为。然后编译器可以利用 trait bound 信息检查代码中所用到的具体类型是否提供了正确的行为。在动态类型语言中如果我们调用了一个未定义的方法会在运行时出现错误。Rust 将这些错误移动到了编译时,甚至在代码能够运行之前就强迫我们修复问题。另外,我们也无需编写运行时检查行为的代码,因为在编译时就已经检查过了。这样既提升了性能又不必放弃泛型的灵活性。
[using-trait-objects-that-allow-for-values-of-different-types]: [using-trait-objects-that-allow-for-values-of-different-types]:
ch17-02-trait-objects.html#为使用不同类型的值而设计的-trait-对象 ch17-02-trait-objects.html#顾及不同类型值的-trait-对象
[methods]: ch05-03-method-syntax.html#定义方法 [methods]: ch05-03-method-syntax.html#定义方法

@ -1,4 +1,4 @@
## 使用生命周期确保引用有效 ## 生命周期确保引用有效
> [ch10-03-lifetime-syntax.md](https://github.com/rust-lang/book/blob/main/src/ch10-03-lifetime-syntax.md) > [ch10-03-lifetime-syntax.md](https://github.com/rust-lang/book/blob/main/src/ch10-03-lifetime-syntax.md)
> <br> > <br>

@ -321,7 +321,7 @@ Cargo 编译并运行了测试。可以看到 `running 1 test` 这一行。下
[concatenation-with-the--operator-or-the-format-macro]: [concatenation-with-the--operator-or-the-format-macro]:
ch08-02-strings.html#使用--运算符或-format-宏拼接字符串 ch08-02-strings.html#使用--运算符或-format-宏拼接字符串
[bench]: https://doc.rust-lang.org/unstable-book/library-features/test.html [bench]: https://doc.rust-lang.org/unstable-book/library-features/test.html
[ignoring]: ch11-02-running-tests.html#ignoring-some-tests-unless-specifically-requested [ignoring]: ch11-02-running-tests.html#除非特别指定否则忽略某些测试
[subset]: ch11-02-running-tests.html#running-a-subset-of-tests-by-name [subset]: ch11-02-running-tests.html#running-a-subset-of-tests-by-name
[controlling-how-tests-are-run]: [controlling-how-tests-are-run]:
ch11-02-running-tests.html#控制测试如何运行 ch11-02-running-tests.html#控制测试如何运行

@ -98,7 +98,7 @@ $ cargo test -- --show-output
这运行了所有名字中带有 `add` 的测试,也过滤掉了名为 `one_hundred` 的测试。同时注意测试所在的模块也是测试名称的一部分,所以可以通过模块名来运行一个模块中的所有测试。 这运行了所有名字中带有 `add` 的测试,也过滤掉了名为 `one_hundred` 的测试。同时注意测试所在的模块也是测试名称的一部分,所以可以通过模块名来运行一个模块中的所有测试。
### 忽略某些测试 ### 除非特别指定否则忽略某些测试
有时一些特定的测试执行起来是非常耗费时间的,所以在大多数运行 `cargo test` 的时候希望能排除它们。虽然可以通过参数列举出所有希望运行的测试来做到,也可以使用 `ignore` 属性来标记耗时的测试并排除它们,如下所示: 有时一些特定的测试执行起来是非常耗费时间的,所以在大多数运行 `cargo test` 的时候希望能排除它们。虽然可以通过参数列举出所有希望运行的测试来做到,也可以使用 `ignore` 属性来标记耗时的测试并排除它们,如下所示:

@ -154,4 +154,4 @@ Rust 的测试功能提供了一个确保即使你改变了函数的实现方式
[paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html [paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html
[separating-modules-into-files]: [separating-modules-into-files]:
ch07-05-separating-modules-into-different-files.html ch07-05-separating-modules-into-different-files.html
[alt-paths]: ch07-05-separating-modules-into-different-files.html#alternate-file-paths [alt-paths]: ch07-05-separating-modules-into-different-files.html#另一种文件路径

@ -170,7 +170,7 @@
### 从 `main` 提取逻辑 ### 从 `main` 提取逻辑
现在我们完成了配置解析的重构:让我们转向程序的逻辑。正如 [“二进制项目的关注分离”](#separation-of-concerns-for-binary-projects) 部分所展开的讨论,我们将提取一个叫做 `run` 的函数来存放目前 `main` 函数中不属于设置配置或处理错误的所有逻辑。一旦完成这些,`main` 函数将简明得足以通过观察来验证,而我们将能够为所有其他逻辑编写测试。 现在我们完成了配置解析的重构:让我们转向程序的逻辑。正如 [“二进制项目的关注分离”](#二进制项目的关注分离) 部分所展开的讨论,我们将提取一个叫做 `run` 的函数来存放目前 `main` 函数中不属于设置配置或处理错误的所有逻辑。一旦完成这些,`main` 函数将简明得足以通过观察来验证,而我们将能够为所有其他逻辑编写测试。
示例 12-11 展示了提取出来的 `run` 函数。目前我们只进行小的增量式的提取函数的改进。我们仍将在 *src/main.rs* 中定义这个函数: 示例 12-11 展示了提取出来的 `run` 函数。目前我们只进行小的增量式的提取函数的改进。我们仍将在 *src/main.rs* 中定义这个函数:
@ -266,8 +266,8 @@ Rust 提示我们的代码忽略了 `Result` 值,它可能表明这里存在
让我们利用这些新创建的模块的优势来进行一些在旧代码中难以展开的工作,这些工作在新代码中非常容易实现,那就是:编写测试! 让我们利用这些新创建的模块的优势来进行一些在旧代码中难以展开的工作,这些工作在新代码中非常容易实现,那就是:编写测试!
[ch13]: ch13-00-functional-features.html [ch13]: ch13-00-functional-features.html
[ch9-custom-types]: ch09-03-to-panic-or-not-to-panic.html#creating-custom-types-for-validation [ch9-custom-types]: ch09-03-to-panic-or-not-to-panic.html#创建自定义类型进行有效性验证
[ch9-error-guidelines]: ch09-03-to-panic-or-not-to-panic.html#guidelines-for-error-handling [ch9-error-guidelines]: ch09-03-to-panic-or-not-to-panic.html#错误处理指导原则
[ch9-result]: ch09-02-recoverable-errors-with-result.html [ch9-result]: ch09-02-recoverable-errors-with-result.html
[ch17]: ch17-00-oop.html [ch17]: ch17-00-oop.html
[ch9-question-mark]: ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator [ch9-question-mark]: ch09-02-recoverable-errors-with-result.html#传播错误的简写-运算符

@ -53,7 +53,7 @@
Rust 不可能知道我们需要的是哪一个参数,所以需要告诉它。因为参数 `contents` 包含了所有的文本而且我们希望返回匹配的那部分文本,所以我们知道 `contents` 是应该要使用生命周期语法来与返回值相关联的参数。 Rust 不可能知道我们需要的是哪一个参数,所以需要告诉它。因为参数 `contents` 包含了所有的文本而且我们希望返回匹配的那部分文本,所以我们知道 `contents` 是应该要使用生命周期语法来与返回值相关联的参数。
其他语言中并不需要你在函数签名中将参数与返回值相关联。所以这么做可能仍然感觉有些陌生,随着时间的推移这将会变得越来越容易。你可能想要将这个例子与第十章中 [“生命周期与引用有效性”][validating-references-with-lifetimes] 部分做对比。 其他语言中并不需要你在函数签名中将参数与返回值相关联。所以这么做可能仍然感觉有些陌生,随着时间的推移这将会变得越来越容易。你可能想要将这个例子与第十章中 [“生命周期确保引用有效”][validating-references-with-lifetimes] 部分做对比。
现在运行测试: 现在运行测试:
@ -159,8 +159,8 @@ Rust 有一个有助于一行一行遍历字符串的方法,出于方便它被
为了使这个项目更丰满,我们将简要的展示如何处理环境变量和打印到标准错误,这两者在编写命令行程序时都很有用。 为了使这个项目更丰满,我们将简要的展示如何处理环境变量和打印到标准错误,这两者在编写命令行程序时都很有用。
[validating-references-with-lifetimes]: [validating-references-with-lifetimes]:
ch10-03-lifetime-syntax.html#生命周期与引用有效性 ch10-03-lifetime-syntax.html#生命周期确保引用有效
[ch11-anatomy]: ch11-01-writing-tests.html#the-anatomy-of-a-test-function [ch11-anatomy]: ch11-01-writing-tests.html#测试函数剖析
[ch10-lifetimes]: ch10-03-lifetime-syntax.html [ch10-lifetimes]: ch10-03-lifetime-syntax.html
[ch3-iter]: ch03-05-control-flow.html#使用-for-遍历集合 [ch3-iter]: ch03-05-control-flow.html#使用-for-遍历集合
[ch13-iterators]: ch13-02-iterators.html [ch13-iterators]: ch13-02-iterators.html

@ -137,4 +137,4 @@ box 只提供了间接存储和堆分配;它们并没有任何其他特殊的
`Box<T>` 类型是一个智能指针,因为它实现了 `Deref` trait它允许 `Box<T>` 值被当作引用对待。当 `Box<T>` 值离开作用域时,由于 `Box<T>` 类型 `Drop` trait 的实现box 所指向的堆数据也会被清除。这两个 trait 对于在本章余下讨论的其他智能指针所提供的功能中,将会更为重要。让我们更详细的探索一下这两个 trait。 `Box<T>` 类型是一个智能指针,因为它实现了 `Deref` trait它允许 `Box<T>` 值被当作引用对待。当 `Box<T>` 值离开作用域时,由于 `Box<T>` 类型 `Drop` trait 的实现box 所指向的堆数据也会被清除。这两个 trait 对于在本章余下讨论的其他智能指针所提供的功能中,将会更为重要。让我们更详细的探索一下这两个 trait。
[trait-objects]: ch17-02-trait-objects.html#为使用不同类型的值而设计的-trait-对象 [trait-objects]: ch17-02-trait-objects.html#顾及不同类型值的-trait-对象

@ -166,5 +166,5 @@ Rust 在发现类型和 trait 实现满足三种情况时会进行 Deref 强制
第三个情况有些微妙Rust 也会将可变引用强转为不可变引用。但是反之是 **不可能** 的不可变引用永远也不能强转为可变引用。因为根据借用规则如果有一个可变引用其必须是这些数据的唯一引用否则程序将无法编译。将一个可变引用转换为不可变引用永远也不会打破借用规则。将不可变引用转换为可变引用则需要初始的不可变引用是数据唯一的不可变引用而借用规则无法保证这一点。因此Rust 无法假设将不可变引用转换为可变引用是可能的。 第三个情况有些微妙Rust 也会将可变引用强转为不可变引用。但是反之是 **不可能** 的不可变引用永远也不能强转为可变引用。因为根据借用规则如果有一个可变引用其必须是这些数据的唯一引用否则程序将无法编译。将一个可变引用转换为不可变引用永远也不会打破借用规则。将不可变引用转换为可变引用则需要初始的不可变引用是数据唯一的不可变引用而借用规则无法保证这一点。因此Rust 无法假设将不可变引用转换为可变引用是可能的。
[impl-trait]: ch10-02-traits.html#implementing-a-trait-on-a-type [impl-trait]: ch10-02-traits.html#为类型实现-trait
[tuple-structs]: ch05-01-defining-structs.html#使用没有命名字段的元组结构体来创建不同的类型 [tuple-structs]: ch05-01-defining-structs.html#使用没有命名字段的元组结构体来创建不同的类型

@ -72,7 +72,7 @@
<span class="caption">示例 15-19打印出引用计数</span> <span class="caption">示例 15-19打印出引用计数</span>
在程序中每个引用计数变化的点,会打印出引用计数,其值可以通过调用 `Rc::strong_count` 函数获得。这个函数叫做 `strong_count` 而不是 `count` 是因为 `Rc<T>` 也有 `weak_count`;在 [“避免引用循环:将 `Rc<T>` 变为 `Weak<T>`”](ch15-06-reference-cycles.html#preventing-reference-cycles-turning-an-rct-into-a-weakt) 部分会讲解 `weak_count` 的用途。 在程序中每个引用计数变化的点,会打印出引用计数,其值可以通过调用 `Rc::strong_count` 函数获得。这个函数叫做 `strong_count` 而不是 `count` 是因为 `Rc<T>` 也有 `weak_count`;在 [“避免引用循环:将 `Rc<T>` 变为 `Weak<T>`”](ch15-06-reference-cycles.html#避免引用循环将-rct-变为-weakt) 部分会讲解 `weak_count` 的用途。
这段代码会打印出: 这段代码会打印出:
@ -86,4 +86,4 @@
通过不可变引用, `Rc<T>` 允许在程序的多个部分之间只读地共享数据。如果 `Rc<T>` 也允许多个可变引用,则会违反第四章讨论的借用规则之一:相同位置的多个可变借用可能造成数据竞争和不一致。不过可以修改数据是非常有用的!在下一部分,我们将讨论内部可变性模式和 `RefCell<T>` 类型,它可以与 `Rc<T>` 结合使用来处理不可变性的限制。 通过不可变引用, `Rc<T>` 允许在程序的多个部分之间只读地共享数据。如果 `Rc<T>` 也允许多个可变引用,则会违反第四章讨论的借用规则之一:相同位置的多个可变借用可能造成数据竞争和不一致。不过可以修改数据是非常有用的!在下一部分,我们将讨论内部可变性模式和 `RefCell<T>` 类型,它可以与 `Rc<T>` 结合使用来处理不可变性的限制。
[preventing-ref-cycles]: ch15-06-reference-cycles.html#preventing-reference-cycles-turning-an-rct-into-a-weakt [preventing-ref-cycles]: ch15-06-reference-cycles.html#避免引用循环将-rct-变为-weakt

@ -77,7 +77,7 @@
还需注意示例 19-1 和 19-3 中创建了同时指向相同内存位置 `num` 的裸指针 `*const i32``*mut i32`。相反如果尝试同时创建 `num` 的不可变和可变引用,将无法通过编译,因为 Rust 的所有权规则不允许在拥有任何不可变引用的同时再创建一个可变引用。通过裸指针,就能够同时创建同一地址的可变指针和不可变指针,若通过可变指针修改数据,则可能潜在造成数据竞争。请多加小心! 还需注意示例 19-1 和 19-3 中创建了同时指向相同内存位置 `num` 的裸指针 `*const i32``*mut i32`。相反如果尝试同时创建 `num` 的不可变和可变引用,将无法通过编译,因为 Rust 的所有权规则不允许在拥有任何不可变引用的同时再创建一个可变引用。通过裸指针,就能够同时创建同一地址的可变指针和不可变指针,若通过可变指针修改数据,则可能潜在造成数据竞争。请多加小心!
既然存在这么多的危险,为何还要使用裸指针呢?一个主要的应用场景便是调用 C 代码接口,这在下一部分 [“调用不安全函数或方法”](#calling-an-unsafe-function-or-method) 中会讲到。另一个场景是构建借用检查器无法理解的安全抽象。让我们先介绍不安全函数,接着看一看使用不安全代码的安全抽象的例子。 既然存在这么多的危险,为何还要使用裸指针呢?一个主要的应用场景便是调用 C 代码接口,这在下一部分 [“调用不安全函数或方法”](#调用不安全函数或方法) 中会讲到。另一个场景是构建借用检查器无法理解的安全抽象。让我们先介绍不安全函数,接着看一看使用不安全代码的安全抽象的例子。
### 调用不安全函数或方法 ### 调用不安全函数或方法

@ -4,7 +4,7 @@
> <br> > <br>
> commit 95e931170404cb98d476b19017cbbdbc00d0834d > commit 95e931170404cb98d476b19017cbbdbc00d0834d
第十章 [“trait定义共享的行为”][traits-defining-shared-behavior] 部分,我们第一次涉及到了 trait不过我们并没有覆盖一些较为高级的细节。现在我们更加了解 Rust 了,可以深入理解其本质了。 第十章 [“trait定义共行为”][traits-defining-shared-behavior] 部分,我们第一次涉及到了 trait不过我们并没有覆盖一些较为高级的细节。现在我们更加了解 Rust 了,可以深入理解其本质了。
### 关联类型在 trait 定义中指定占位符类型 ### 关联类型在 trait 定义中指定占位符类型
@ -273,6 +273,6 @@ Rust 既不能避免一个 trait 与另一个 trait 拥有相同名称的方法
[newtype]: ch19-03-advanced-traits.html#newtype-模式用以在外部类型上实现外部-trait [newtype]: ch19-03-advanced-traits.html#newtype-模式用以在外部类型上实现外部-trait
[implementing-a-trait-on-a-type]: ch10-02-traits.html#为类型实现-trait [implementing-a-trait-on-a-type]: ch10-02-traits.html#为类型实现-trait
[traits-defining-shared-behavior]: ch10-02-traits.html#trait定义共享的行为 [traits-defining-shared-behavior]: ch10-02-traits.html#trait定义共行为
[smart-pointer-deref]: ch15-02-deref.html#通过实现-deref-trait-将某类型像引用一样处理 [smart-pointer-deref]: ch15-02-deref.html#通过实现-deref-trait-将某类型像引用一样处理
[tuple-structs]: ch05-01-defining-structs.html#使用没有命名字段的元组结构体来创建不同的类型 [tuple-structs]: ch05-01-defining-structs.html#使用没有命名字段的元组结构体来创建不同的类型

@ -136,7 +136,7 @@ Rust 需要知道应该为特定类型的值分配多少内存,同时所有同
那么该怎么办呢?你已经知道了这种问题的答案:`s1` 和 `s2` 的类型是 `&str` 而不是 `str`。如果你回想第四章 [“字符串 slice”][string-slices] 部分slice 数据结构仅仅储存了开始位置和 slice 的长度。所以虽然 `&T` 是一个储存了 `T` 所在的内存位置的单个值,`&str` 则是 **两个** 值:`str` 的地址和其长度。这样,`&str` 就有了一个在编译时可以知道的大小:它是 `usize` 长度的两倍。也就是说,我们总是知道 `&str` 的大小,而无论其引用的字符串是多长。这里是 Rust 中动态大小类型的常规用法:它们有一些额外的元信息来储存动态信息的大小。这引出了动态大小类型的黄金规则:必须将动态大小类型的值置于某种指针之后。 那么该怎么办呢?你已经知道了这种问题的答案:`s1` 和 `s2` 的类型是 `&str` 而不是 `str`。如果你回想第四章 [“字符串 slice”][string-slices] 部分slice 数据结构仅仅储存了开始位置和 slice 的长度。所以虽然 `&T` 是一个储存了 `T` 所在的内存位置的单个值,`&str` 则是 **两个** 值:`str` 的地址和其长度。这样,`&str` 就有了一个在编译时可以知道的大小:它是 `usize` 长度的两倍。也就是说,我们总是知道 `&str` 的大小,而无论其引用的字符串是多长。这里是 Rust 中动态大小类型的常规用法:它们有一些额外的元信息来储存动态信息的大小。这引出了动态大小类型的黄金规则:必须将动态大小类型的值置于某种指针之后。
可以将 `str` 与所有类型的指针结合:比如 `Box<str>``Rc<str>`。事实上之前我们已经见过了不过是另一个动态大小类型trait。每一个 trait 都是一个可以通过 trait 名称来引用的动态大小类型。在第十七章 [“为使用不同类型的值而设计的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分,我们提到了为了将 trait 用于 trait 对象,必须将它们放入指针之后,比如 `&dyn Trait``Box<dyn Trait>``Rc<dyn Trait>` 也可以)。 可以将 `str` 与所有类型的指针结合:比如 `Box<str>``Rc<str>`。事实上之前我们已经见过了不过是另一个动态大小类型trait。每一个 trait 都是一个可以通过 trait 名称来引用的动态大小类型。在第十七章 [顾及不同类型值的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分,我们提到了为了将 trait 用于 trait 对象,必须将它们放入指针之后,比如 `&dyn Trait``Box<dyn Trait>``Rc<dyn Trait>` 也可以)。
为了处理 DSTRust 提供了 `Sized` trait 来决定一个类型的大小是否在编译时可知。这个 trait 自动为编译器在编译时就知道大小的类型实现。另外Rust 隐式的为每一个泛型函数增加了 `Sized` bound。也就是说对于如下泛型函数定义 为了处理 DSTRust 提供了 `Sized` trait 来决定一个类型的大小是否在编译时可知。这个 trait 自动为编译器在编译时就知道大小的类型实现。另外Rust 隐式的为每一个泛型函数增加了 `Sized` bound。也就是说对于如下泛型函数定义
@ -166,7 +166,7 @@ Rust 需要知道应该为特定类型的值分配多少内存,同时所有同
ch17-01-what-is-oo.html#封装隐藏了实现细节 ch17-01-what-is-oo.html#封装隐藏了实现细节
[string-slices]: ch04-03-slices.html#字符串-slice [string-slices]: ch04-03-slices.html#字符串-slice
[the-match-control-flow-operator]: [the-match-control-flow-operator]:
ch06-02-match.html#match-控制流运算符 ch06-02-match.html#match-控制流结构
[using-trait-objects-that-allow-for-values-of-different-types]: [using-trait-objects-that-allow-for-values-of-different-types]:
ch17-02-trait-objects.html#为使用不同类型的值而设计的-trait-对象 ch17-02-trait-objects.html#顾及不同类型值的-trait-对象
[using-the-newtype-pattern]: ch19-03-advanced-traits.html#newtype-模式用以在外部类型上实现外部-trait [using-the-newtype-pattern]: ch19-03-advanced-traits.html#newtype-模式用以在外部类型上实现外部-trait

@ -72,10 +72,10 @@
{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}} {{#rustdoc_include ../listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}}
``` ```
这段代码正好可以编译。关于 trait 对象的更多内容,请回顾第十七章的 [“为使用不同类型的值而设计的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分。 这段代码正好可以编译。关于 trait 对象的更多内容,请回顾第十七章的 [顾及不同类型值的 trait 对象”][using-trait-objects-that-allow-for-values-of-different-types] 部分。
接下来让我们学习宏! 接下来让我们学习宏!
[advanced-traits]: ch19-03-advanced-traits.html#高级-trait [advanced-traits]: ch19-03-advanced-traits.html#高级-trait
[enum-values]: ch06-01-defining-an-enum.html#枚举值 [enum-values]: ch06-01-defining-an-enum.html#枚举值
[using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#为使用不同类型的值而设计的-trait-对象 [using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#顾及不同类型值的-trait-对象

@ -119,7 +119,7 @@
{{#include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt}} {{#include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt}}
``` ```
现在有了一个警告和一个错误。暂时先忽略警告,发生错误是因为并没有 `ThreadPool` 上的 `execute` 方法。回忆 [“创建有限数量的线程”](#creating-a-finite-number-of-threads) 部分我们决定线程池应该有与 `thread::spawn` 类似的接口,同时我们将实现 `execute` 函数来获取传递的闭包并将其传递给池中的空闲线程执行。 现在有了一个警告和一个错误。暂时先忽略警告,发生错误是因为并没有 `ThreadPool` 上的 `execute` 方法。回忆 [“创建有限数量的线程”](#创建有限数量的线程) 部分我们决定线程池应该有与 `thread::spawn` 类似的接口,同时我们将实现 `execute` 函数来获取传递的闭包并将其传递给池中的空闲线程执行。
我们会在 `ThreadPool` 上定义 `execute` 函数来获取一个闭包参数。回忆第十三章的 [“将被捕获的值移出闭包和 `Fn` trait”][fn-traits] 部分,闭包作为参数时可以使用三个不同的 trait`Fn`、`FnMut` 和 `FnOnce`。我们需要决定这里应该使用哪种闭包。最终需要实现的类似于标准库的 `thread::spawn`,所以我们可以观察 `thread::spawn` 的签名在其参数中使用了何种 bound。查看文档会发现 我们会在 `ThreadPool` 上定义 `execute` 函数来获取一个闭包参数。回忆第十三章的 [“将被捕获的值移出闭包和 `Fn` trait”][fn-traits] 部分,闭包作为参数时可以使用三个不同的 trait`Fn`、`FnMut` 和 `FnOnce`。我们需要决定这里应该使用哪种闭包。最终需要实现的类似于标准库的 `thread::spawn`,所以我们可以观察 `thread::spawn` 的签名在其参数中使用了何种 bound。查看文档会发现

Loading…
Cancel
Save