mirror of
https://github.com/KaiserY/trpl-zh-cn
synced 2024-11-14 21:11:31 +08:00
Merge pull request #309 from flw-cn/fix/add-eol
Style: 部分文件的最后一行没有以行结束符结尾,现已修复
This commit is contained in:
commit
61d8ec473c
@ -4,4 +4,4 @@
|
||||
> <br>
|
||||
> commit 1fedfc4b96c2017f64ecfcf41a0a07e2e815f24f
|
||||
|
||||
附录部分包含一些在你的 Rust 之旅中可能用到的参考资料。
|
||||
附录部分包含一些在你的 Rust 之旅中可能用到的参考资料。
|
||||
|
@ -165,4 +165,4 @@ $ rustup component add rls-preview
|
||||
|
||||
请查看 [其文档][rls] 来了解 `rls` 的更多信息。
|
||||
|
||||
[rls]: https://github.com/rust-lang-nursery/rls
|
||||
[rls]: https://github.com/rust-lang-nursery/rls
|
||||
|
@ -24,4 +24,4 @@ Rust 语言和编译器有一个为期 6 周的发布循环。这意味着用户
|
||||
|
||||
有一点需要明确:大部分功能在所有版本中都能使用。开发者使用任何 Rust 版本将能继续接收最新稳定版的改进。然而在一些情况,主要是增加了新关键字的时候,则可能出现了只能用于新版本的功能。只需切换版本即可利用新版本的功能。
|
||||
|
||||
请查看 [Edition Guide](https://rust-lang-nursery.github.io/edition-guide/) 了解更多细节,这是一个完全介绍版本的书籍,包括如何通过 `cargo fix` 自动将代码迁移到新版本。
|
||||
请查看 [Edition Guide](https://rust-lang-nursery.github.io/edition-guide/) 了解更多细节,这是一个完全介绍版本的书籍,包括如何通过 `cargo fix` 自动将代码迁移到新版本。
|
||||
|
@ -22,4 +22,4 @@
|
||||
- [Polski](https://github.com/paytchoo/book-pl)
|
||||
- [עברית](https://github.com/idanmel/rust-book-heb)
|
||||
- [Cebuano](https://github.com/agentzero1/book)
|
||||
- [Tagalog](https://github.com/josephace135/book)
|
||||
- [Tagalog](https://github.com/josephace135/book)
|
||||
|
@ -112,4 +112,4 @@ $ rustup override set nightly
|
||||
|
||||
如果功能被接受了,在 Rust 仓库会打开一个 issue,人们就可以实现它。实现功能的人当人可能不是最初提议功能的人!当实现完成后,其会合并到 `master` 分支并位于一个功能开关(feature gate)之后,正如 [“不稳定功能”(#unstable-features) 部分所讨论的。
|
||||
|
||||
在稍后的某个时间,一旦使用 nightly 版的 Rust 团队能够尝试这个功能了,团队成员会讨论这个功能,它如何在 nightly 中工作,并决定是否应该进入稳定版。如果决定继续推进,功能开关会移除,然后这个功能就被认为是稳定的了!并会在新的稳定版 Rust 中出现。
|
||||
在稍后的某个时间,一旦使用 nightly 版的 Rust 团队能够尝试这个功能了,团队成员会讨论这个功能,它如何在 nightly 中工作,并决定是否应该进入稳定版。如果决定继续推进,功能开关会移除,然后这个功能就被认为是稳定的了!并会在新的稳定版 Rust 中出现。
|
||||
|
@ -8,4 +8,4 @@
|
||||
|
||||
* 在 Linux、macOS 和 Windows 上安装 Rust
|
||||
* 编写一个打印 `Hello, world!` 的程序
|
||||
* 使用 Rust 的包管理器和构建系统 `cargo`
|
||||
* 使用 Rust 的包管理器和构建系统 `cargo`
|
||||
|
@ -94,4 +94,4 @@ rustc x.y.z (abcabcabc yyyy-mm-dd)
|
||||
|
||||
安装程序也自带一份文档的本地拷贝,可以离线阅读。运行 `rustup doc` 在浏览器中查看本地文档。
|
||||
|
||||
任何时候,如果你拿不准标准库中的类型或函数的用途和用法,请查阅应用程序接口(application programming interface,API)文档!
|
||||
任何时候,如果你拿不准标准库中的类型或函数的用途和用法,请查阅应用程序接口(application programming interface,API)文档!
|
||||
|
@ -4,4 +4,4 @@
|
||||
> <br>
|
||||
> commit 1fedfc4b96c2017f64ecfcf41a0a07e2e815f24f
|
||||
|
||||
所有权(系统)是 Rust 最独特的功能,其令 Rust 无需垃圾回收(garbage collector)即可保障内存安全。因此,理解 Rust 中所有权如何工作是十分重要的。本章,我们将讲到所有权以及相关功能:借用、slice 以及 Rust 如何在内存中布局数据。
|
||||
所有权(系统)是 Rust 最独特的功能,其令 Rust 无需垃圾回收(garbage collector)即可保障内存安全。因此,理解 Rust 中所有权如何工作是十分重要的。本章,我们将讲到所有权以及相关功能:借用、slice 以及 Rust 如何在内存中布局数据。
|
||||
|
@ -28,4 +28,4 @@ main.rs
|
||||
|
||||
如果包同时包含 *src/main.rs* 和 *src/lib.rs*,那么它带有两个 crate:一个库和一个二进制项目,同名。如果只有其中之一,则包将只有一个库或者二进制 crate。包可以带有多个二进制 crate,需将其文件置于 *src/bin* 目录;每个文件将是一个单独的二进制 crate。
|
||||
|
||||
接下来让我们讨论模块!
|
||||
接下来让我们讨论模块!
|
||||
|
@ -83,4 +83,4 @@ How dreary to be somebody!
|
||||
|
||||
在这一章中,我们回顾了目前为止的一些主要章节并涉及了如何在 Rust 环境中进行常规的 I/O 操作。通过使用命令行参数、文件、环境变量和打印错误的 `eprintln!` 宏,现在你已经准备好编写命令行程序了。通过结合前几章的知识,你的代码将会是组织良好的,并能有效的将数据存储到合适的数据结构中、更好的处理错误,并且还是经过良好测试的。
|
||||
|
||||
接下来,让我们探索一些 Rust 中受函数式编程语言影响的功能:闭包和迭代器。
|
||||
接下来,让我们探索一些 Rust 中受函数式编程语言影响的功能:闭包和迭代器。
|
||||
|
@ -52,4 +52,4 @@ for i in 12..buffer.len() {
|
||||
|
||||
闭包和迭代器是 Rust 受函数式编程语言观念所启发的功能。他们对 Rust 以底层的性能来明确的表达高级概念的能力有很大贡献。闭包和迭代器的实现达到了不影响运行时性能的程度。这正是 Rust 竭力提供零成本抽象的目标的一部分。
|
||||
|
||||
现在我们改进了我们 I/O 项目的(代码)表现力,让我们看一看更多 `cargo` 的功能,他们将帮助我们准备好将项目分享给世界。
|
||||
现在我们改进了我们 I/O 项目的(代码)表现力,让我们看一看更多 `cargo` 的功能,他们将帮助我们准备好将项目分享给世界。
|
||||
|
@ -12,4 +12,4 @@
|
||||
* 从 [crates.io](https://crates.io)<!-- ignore --> 安装二进制文件
|
||||
* 使用自定义的命令来扩展 Cargo
|
||||
|
||||
Cargo 的功能不止本章所介绍的,关于其功能的全部解释,请查看 [文档](http://doc.rust-lang.org/cargo/)
|
||||
Cargo 的功能不止本章所介绍的,关于其功能的全部解释,请查看 [文档](http://doc.rust-lang.org/cargo/)
|
||||
|
@ -333,4 +333,4 @@ $ cargo yank --vers 1.0.1
|
||||
$ cargo yank --vers 1.0.1 --undo
|
||||
```
|
||||
|
||||
撤回 **并没有** 删除任何代码。举例来说,撤回功能并不意在删除不小心上传的秘密信息。如果出现了这种情况,请立即重新设置这些秘密信息。
|
||||
撤回 **并没有** 删除任何代码。举例来说,撤回功能并不意在删除不小心上传的秘密信息。如果出现了这种情况,请立即重新设置这些秘密信息。
|
||||
|
@ -20,4 +20,4 @@ Updating registry `https://github.com/rust-lang/crates.io-index`
|
||||
Installing ~/.cargo/bin/rg
|
||||
```
|
||||
|
||||
最后一行输出展示了安装的二进制文件的位置和名称,在这里 `ripgrep` 被命名为 `rg`。只要你像上面提到的那样将安装目录加入 `$PATH`,就可以运行 `rg --help` 并开始使用一个更快更 Rust 的工具来搜索文件了!
|
||||
最后一行输出展示了安装的二进制文件的位置和名称,在这里 `ripgrep` 被命名为 `rg`。只要你像上面提到的那样将安装目录加入 `$PATH`,就可以运行 `rg --help` 并开始使用一个更快更 Rust 的工具来搜索文件了!
|
||||
|
@ -8,4 +8,4 @@ Cargo 的设计使得开发者可以通过新的子命令来对 Cargo 进行扩
|
||||
|
||||
## 总结
|
||||
|
||||
通过 Cargo 和 [crates.io](https://crates.io)<!-- ignore --> 来分享代码是使得 Rust 生态环境可以用于许多不同的任务的重要组成部分。Rust 的标准库是小而稳定的,不过 crate 易于分享和使用,并采用一个不同语言自身的时间线来提供改进。不要羞于在 [crates.io](https://crates.io)<!-- ignore --> 上共享对你有用的代码;因为它很有可能对别人也很有用!
|
||||
通过 Cargo 和 [crates.io](https://crates.io)<!-- ignore --> 来分享代码是使得 Rust 生态环境可以用于许多不同的任务的重要组成部分。Rust 的标准库是小而稳定的,不过 crate 易于分享和使用,并采用一个不同语言自身的时间线来提供改进。不要羞于在 [crates.io](https://crates.io)<!-- ignore --> 上共享对你有用的代码;因为它很有可能对别人也很有用!
|
||||
|
@ -122,4 +122,4 @@ CustomSmartPointer dropped before the end of main.
|
||||
|
||||
我们也无需担心意外的清理掉仍在使用的值,这会造成编译器错误:所有权系统确保引用总是有效的,也会确保 `drop` 只会在值不再被使用时被调用一次。
|
||||
|
||||
现在我们学习了 `Box<T>` 和一些智能指针的特性,让我们聊聊一些其他标准库中定义的智能指针。
|
||||
现在我们学习了 `Box<T>` 和一些智能指针的特性,让我们聊聊一些其他标准库中定义的智能指针。
|
||||
|
@ -38,4 +38,4 @@ Rust 的并发模型中一个有趣的方面是:语言本身对并发知之 **
|
||||
|
||||
Rust 提供了用于消息传递的通道,和像 `Mutex<T>` 和 `Arc<T>` 这样可以安全的用于并发上下文的智能指针。类型系统和借用检查器会确保这些场景中的代码,不会出现数据竞争和无效的引用。一旦代码可以编译了,我们就可以坚信这些代码可以正确的运行于多线程环境,而不会出现其他语言中经常出现的那些难以追踪的 bug。并发编程不再是什么可怕的概念:无所畏惧地并发吧!
|
||||
|
||||
接下来,让我们讨论一下当 Rust 程序变得更大时,有哪些符合语言习惯的问题建模方法和结构化解决方案,以及 Rust 的风格是如何与面向对象编程(Object Oriented Programming)中那些你所熟悉的概念相联系的。
|
||||
接下来,让我们讨论一下当 Rust 程序变得更大时,有哪些符合语言习惯的问题建模方法和结构化解决方案,以及 Rust 的风格是如何与面向对象编程(Object Oriented Programming)中那些你所熟悉的概念相联系的。
|
||||
|
@ -15,4 +15,4 @@
|
||||
* 高级函数和闭包:函数指针和返回闭包
|
||||
* 宏:定义在编译时定义更多更多代码的方式
|
||||
|
||||
对所有人而言,这都是一个介绍 Rust 迷人特性的宝典!让我们翻开它吧!
|
||||
对所有人而言,这都是一个介绍 Rust 迷人特性的宝典!让我们翻开它吧!
|
||||
|
@ -359,4 +359,4 @@ pub fn sql(input: TokenStream) -> TokenStream {
|
||||
|
||||
好的!现在我们学习了 Rust 并不常用但在特定情况下你可能用得着的功能。我们介绍了很多复杂的主题,这样若你在错误信息提示或阅读他人代码时遇到他们,至少可以说之前已经见过这些概念和语法了。你可以使用本章作为一个解决方案的参考。
|
||||
|
||||
接下来,我们将再开始一个项目,将本书所学的所有内容付与实践!
|
||||
接下来,我们将再开始一个项目,将本书所学的所有内容付与实践!
|
||||
|
@ -857,4 +857,4 @@ impl Worker {
|
||||
|
||||
这段代码可以编译和运行,但是并不会产生所期望的线程行为:一个慢请求仍然会导致其他请求等待执行。其原因有些微妙:`Mutex` 结构体没有公有 `unlock` 方法,因为锁的所有权依赖 `lock` 方法返回的 `LockResult<MutexGuard<T>>` 中 `MutexGuard<T>` 的生命周期。这允许借用检查器在编译时确保绝不会在没有持有锁的情况下访问由 `Mutex` 守护的资源,不过如果没有认真的思考 `MutexGuard<T>` 的生命周期的话,也可能会导致比预期更久的持有锁。因为 `while` 表达式中的值在整个块一直处于作用域中,`job.call_box()` 调用的过程中其仍然持有锁,这意味着其他 worker 不能接收任务。
|
||||
|
||||
相反通过使用 `loop` 并在循环块之内而不是之外获取锁和任务,`lock` 方法返回的 `MutexGuard` 在 `let job` 语句结束之后立刻就被丢弃了。这确保了 `recv` 调用过程中持有锁,而在 `job.call_box()` 调用前锁就被释放了,这就允许并发处理多个请求了。
|
||||
相反通过使用 `loop` 并在循环块之内而不是之外获取锁和任务,`lock` 方法返回的 `MutexGuard` 在 `let job` 语句结束之后立刻就被丢弃了。这确保了 `recv` 调用过程中持有锁,而在 `job.call_box()` 调用前锁就被释放了,这就允许并发处理多个请求了。
|
||||
|
@ -63,4 +63,4 @@ fn handle_connection(mut stream: TcpStream) {
|
||||
|
||||
不同于分配无限的线程,线程池中将有固定数量的等待线程。当新进请求时,将请求发送到线程池中做处理。线程池会维护一个接收请求的队列。每一个线程会从队列中取出一个请求,处理请求,接着向对队列索取另一个请求。通过这种设计,则可以并发处理 `N` 个请求,其中 `N` 为线程数。这仍然意味着 `N` 个慢请求会阻塞队列中的请求,不过确实将能够处理的慢请求数量从一增加到了 `N`。
|
||||
|
||||
这个设计是多种改善 web server 吞吐量的方法之一。不过本书并不是有关 web server 的,所以这一种方法是我们将要涉及的。其他的方法有 fork/join 模型和单线程异步 I/O 模型。如果你对这个主题感兴趣,则可以阅读更多关于其他解决方案的内容并尝试用 Rust 实现他们;对于一个像 Rust 这样的底层语言,所有这些方法都是可能的。
|
||||
这个设计是多种改善 web server 吞吐量的方法之一。不过本书并不是有关 web server 的,所以这一种方法是我们将要涉及的。其他的方法有 fork/join 模型和单线程异步 I/O 模型。如果你对这个主题感兴趣,则可以阅读更多关于其他解决方案的内容并尝试用 Rust 实现他们;对于一个像 Rust 这样的底层语言,所有这些方法都是可能的。
|
||||
|
@ -211,4 +211,4 @@ warning: unused variable: `f`, #[warn(unused_variables)] on by default
|
||||
|
||||
现在就只有警告了!能够编译了!注意如果尝试 `cargo run` 运行程序并在浏览器中发起请求,仍会在浏览器中出现在本章开始时那样的错误。这个库实际上还没有调用传递给 `execute` 的闭包!
|
||||
|
||||
> 一个你可能听说过的关于像 Haskell 和 Rust 这样有严格编译器的语言的说法是“如果代码能够编译,它就能工作”。这是一个提醒大家的好时机,这只是一个说法和一种有时存在的感觉,实际上并不是完全正确的。我们的项目可以编译,不过它绝对没有做任何工作!如果构建一个真实且功能完整的项目,则需花费大量的时间来开始编写单元测试来检查代码能否编译**并且**拥有期望的行为。
|
||||
> 一个你可能听说过的关于像 Haskell 和 Rust 这样有严格编译器的语言的说法是“如果代码能够编译,它就能工作”。这是一个提醒大家的好时机,这只是一个说法和一种有时存在的感觉,实际上并不是完全正确的。我们的项目可以编译,不过它绝对没有做任何工作!如果构建一个真实且功能完整的项目,则需花费大量的时间来开始编写单元测试来检查代码能否编译**并且**拥有期望的行为。
|
||||
|
@ -475,4 +475,4 @@ impl Worker {
|
||||
|
||||
## 总结
|
||||
|
||||
好极了!你结束了本书的学习!由衷感谢你同我们一道加入这次 Rust 之旅。现在你已经准备好出发并实现自己的 Rust 项目并帮助他人了。请不要忘记我们的社区,这里有其他 Rustaceans 正乐于帮助你迎接 Rust 之路上的任何挑战。
|
||||
好极了!你结束了本书的学习!由衷感谢你同我们一道加入这次 Rust 之旅。现在你已经准备好出发并实现自己的 Rust 项目并帮助他人了。请不要忘记我们的社区,这里有其他 Rustaceans 正乐于帮助你迎接 Rust 之路上的任何挑战。
|
||||
|
@ -182,4 +182,4 @@ impl Worker {
|
||||
|
||||
`Worker` 结构体和其 `new` 函数是私有的,因为外部代码(比如 *src/bin/main.rs* 中的 server)并不需要 `ThreadPool` 中使用 `Worker` 结构体的实现细节。`Worker::new` 函数使用 `id` 参数并储存了使用一个空闭包创建的 `JoinHandle<()>`。
|
||||
|
||||
这段代码能够编译并用指定给 `ThreadPool::new` 的参数创建储存了一系列的 `Worker` 实例,不过**仍然**没有处理 `execute` 中得到的闭包。让我们聊聊接下来怎么做。
|
||||
这段代码能够编译并用指定给 `ThreadPool::new` 的参数创建储存了一系列的 `Worker` 实例,不过**仍然**没有处理 `execute` 中得到的闭包。让我们聊聊接下来怎么做。
|
||||
|
@ -391,4 +391,4 @@ Worker 2 got a job; executing.
|
||||
|
||||
那么这些警告怎么办呢?难道我们没有使用 `workers`、`id` 和 `thread` 字段吗?好吧,目前我们用了所有这些字段存放了一些数据,不过当设置线程池并开始执行代码在通道中向线程发送任务时,我们并没有对数据**进行**任何实际的操作。但是如果不存放这些值,他们将会离开作用域:比如,如果不将 `Vec<Worker>` 值作为 `ThreadPool` 的一部分返回,这个 vector 在 `ThreadPool::new` 的结尾就会被清理。
|
||||
|
||||
那么这些警告有错吗?从某种角度上讲是的,这些警告是错误的,因为我们使用这些字段储存一直需要的数据。从另一种角度来说也不对:使用过后我们也没有做任何操作清理线程池,仅仅通过 <span class="keystroke">ctrl-C</span> 来停止程序并让操作系统为我们清理。下面让我们实现 graceful shutdown 来清理所创建的一切。
|
||||
那么这些警告有错吗?从某种角度上讲是的,这些警告是错误的,因为我们使用这些字段储存一直需要的数据。从另一种角度来说也不对:使用过后我们也没有做任何操作清理线程池,仅仅通过 <span class="keystroke">ctrl-C</span> 来停止程序并让操作系统为我们清理。下面让我们实现 graceful shutdown 来清理所创建的一切。
|
||||
|
Loading…
Reference in New Issue
Block a user