diff --git a/src/ch03-02-data-types.md b/src/ch03-02-data-types.md index 58cdeaf..e2513b0 100644 --- a/src/ch03-02-data-types.md +++ b/src/ch03-02-data-types.md @@ -232,12 +232,14 @@ let a: [i32; 5] = [1, 2, 3, 4, 5]; 这里,`i32` 是每个元素的类型。分号之后,数字 `5` 表明该数组包含五个元素。 -这样编写数组的类型类似于另一个初始化数组的语法:如果你希望创建一个每个元素都相同的数组,可以在中括号内指定其初始值,后跟分号,再后跟数组的长度,如下所示: +以这种方式编写数组的类型看起来类似于初始化数组的另一种语法:如果要为每个元素创建包含相同值的数组,可以指定初始值,后跟分号,然后在方括号中指定数组的长度,如下所示: ```rust let a = [3; 5]; ``` +变量名为 `a` 的数组将包含 `5` 个元素,这些元素的值最初都将被设置为 `3`。这种写法与 `let a = [3, 3, 3, 3, 3];` 效果相同,但更简洁。 + ##### 访问数组元素 数组是一整块分配在栈上的内存。可以使用索引来访问数组的元素,像这样: diff --git a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md index 7710e80..4605209 100644 --- a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md +++ b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md @@ -6,7 +6,7 @@ 当你编写大型程序时,组织你的代码显得尤为重要,因为你想在脑海中通晓整个程序,那几乎是不可能完成的。通过对相关功能进行分组和划分不同功能的代码,你可以清楚在哪里可以找到实现了特定功能的代码,以及在哪里可以改变一个功能的工作方式。 -到目前为止,我们编写的程序都在一个文件的一个模块中。伴随着项目的增长,你可以通过将代码分解为多个模块和多个文件来组织代码。一个包可以包含多个二进制 crate 项和一个可选的 crate 库。伴随着包的增长,你可以将包中的部分代码提取出来,做成独立的 crate,这些 crate 则作为外部依赖项。本章将会涵盖所有这些概念。对于一个由一系列相互关联的包组合而成的超大型项目,Cargo 提供了 “工作空间” 这一功能,我们将在第十四章的 “[Cargo Workspaces](https://github.com/rust-lang/book/blob/master/src/ch14-03-cargo-workspaces.html)” 对此进行讲解。 +到目前为止,我们编写的程序都在一个文件的一个模块中。伴随着项目的增长,你可以通过将代码分解为多个模块和多个文件来组织代码。一个包可以包含多个二进制 crate 项和一个可选的 crate 库。伴随着包的增长,你可以将包中的部分代码提取出来,做成独立的 crate,这些 crate 则作为外部依赖项。本章将会涵盖所有这些概念。对于一个由一系列相互关联的包组合而成的超大型项目,Cargo 提供了 “工作空间” 这一功能,我们将在第十四章的 “[Cargo Workspaces](ch14-03-cargo-workspaces.html)” 对此进行讲解。 除了对功能进行分组以外,封装实现细节可以使你更高级地重用代码:你实现了一个操作后,其他的代码可以通过该代码的公共接口来进行调用,而不需要知道它是如何实现的。你在编写代码时可以定义哪些部分是其他代码可以使用的公共部分,以及哪些部分是你有权更改实现细节的私有部分。这是另一种减少你在脑海中记住项目内容数量的方法。 diff --git a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index 0310a4a..00e52ac 100644 --- a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -13,7 +13,7 @@ 绝对路径和相对路径都后跟一个或多个由双冒号(`::`)分割的标识符。 -让我们回到示例 7-1。我们如何调用 `add_to_waitlist` 函数?还是同样的问题,`add_to_waitlist` 函数的路径是什么?在示例 7-3 中,我们通过删除一些模块和函数,稍微简化了一下我们的代码。我们在 crate 根定义了一个新函数 `eat_at_restaurant`,并在其中展示调用 `add_to_waitlist` 函数的两种方法。`eat_at_restaurant` 函数是我们 crate 库的一个公共API,所以我们使用 `pub` 关键字来标记它。在 “[使用`pub`关键字暴露路径](https://github.com/rust-lang/book/blob/master/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword)” 一节,我们将详细介绍 `pub`。注意,这个例子无法编译通过,我们稍后会解释原因。 +让我们回到示例 7-1。我们如何调用 `add_to_waitlist` 函数?还是同样的问题,`add_to_waitlist` 函数的路径是什么?在示例 7-3 中,我们通过删除一些模块和函数,稍微简化了一下我们的代码。我们在 crate 根定义了一个新函数 `eat_at_restaurant`,并在其中展示调用 `add_to_waitlist` 函数的两种方法。`eat_at_restaurant` 函数是我们 crate 库的一个公共API,所以我们使用 `pub` 关键字来标记它。在 “[使用`pub`关键字暴露路径](ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword)” 一节,我们将详细介绍 `pub`。注意,这个例子无法编译通过,我们稍后会解释原因。 文件名: src/lib.rs diff --git a/src/ch10-03-lifetime-syntax.md b/src/ch10-03-lifetime-syntax.md index 07f062a..9a77ddc 100644 --- a/src/ch10-03-lifetime-syntax.md +++ b/src/ch10-03-lifetime-syntax.md @@ -233,15 +233,14 @@ fn main() { ```text error[E0597]: `string2` does not live long enough - --> src/main.rs:15:5 - | -14 | result = longest(string1.as_str(), string2.as_str()); - | ------- borrow occurs here -15 | } - | ^ `string2` dropped here while still borrowed -16 | println!("The longest string is {}", result); -17 | } - | - borrowed value needs to live until here + --> src/main.rs:6:44 + | +6 | result = longest(string1.as_str(), string2.as_str()); + | ^^^^^^^ borrowed value does not live long enough +7 | } + | - `string2` dropped here while still borrowed +8 | println!("The longest string is {}", result); + | ------ borrow later used here ``` 错误表明为了保证 `println!` 中的 `result` 是有效的,`string2` 需要直到外部作用域结束都是有效的。Rust 知道这些是因为(`longest`)函数的参数和返回值都使用了相同的生命周期参数 `'a`。 diff --git a/src/ch12-03-improving-error-handling-and-modularity.md b/src/ch12-03-improving-error-handling-and-modularity.md index a1309db..bb6edfe 100644 --- a/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/ch12-03-improving-error-handling-and-modularity.md @@ -8,7 +8,7 @@ 第一,`main` 现在进行了两个任务:它解析了参数并打开了文件。对于一个这样的小函数,这并不是一个大问题。然而如果 `main` 中的功能持续增加,`main` 函数处理的独立任务也会增加。当函数承担了更多责任,它就更难以推导,更难以测试,并且更难以在不破坏其他部分的情况下做出修改。最好能分离出功能以便每个函数就负责一个任务。 -这同时也关系到第二个问题:`search` 和 `filename` 是程序中的配置变量,而像 `contents` 则用来执行程序逻辑。随着 `main` 函数的增长,就需要引入更多的变量到作用域中,而当作用域中有更多的变量时,将更难以追踪每个变量的目的。最好能将配置变量组织进一个结构,这样就能使他们的目的更明确了。 +这同时也关系到第二个问题:`query` 和 `filename` 是程序中的配置变量,而像 `contents` 则用来执行程序逻辑。随着 `main` 函数的增长,就需要引入更多的变量到作用域中,而当作用域中有更多的变量时,将更难以追踪每个变量的目的。最好能将配置变量组织进一个结构,这样就能使他们的目的更明确了。 第三个问题是如果打开文件失败我们使用 `expect` 来打印出错误信息,不过这个错误信息只是说 `Something went wrong reading the file`。读取文件失败的原因有多种:例如文件不存在,或者没有打开此文件的权限。目前,无论处于何种情况,我们只是打印出“文件读取出现错误”的信息,这并没有给予使用者具体的信息! diff --git a/src/ch12-04-testing-the-librarys-functionality.md b/src/ch12-04-testing-the-librarys-functionality.md index 693113e..4d7b81d 100644 --- a/src/ch12-04-testing-the-librarys-functionality.md +++ b/src/ch12-04-testing-the-librarys-functionality.md @@ -8,8 +8,8 @@ 在这一部分,我们将遵循测试驱动开发(Test Driven Development, TDD)的模式来逐步增加 `minigrep` 的搜索逻辑。这是一个软件开发技术,它遵循如下步骤: -1. 编写一个会失败的测试,并运行它以确保其因为你期望的原因失败。 -2. 编写或修改刚好足够的代码来使得新的测试通过。 +1. 编写一个失败的测试,并运行它以确保它失败的原因是你所期望的。 +2. 编写或修改足够的代码来使新的测试通过。 3. 重构刚刚增加或修改的代码,并确保测试仍然能通过。 4. 从步骤 1 开始重复! diff --git a/src/ch14-02-publishing-to-crates-io.md b/src/ch14-02-publishing-to-crates-io.md index 0f58116..e5b18a3 100644 --- a/src/ch14-02-publishing-to-crates-io.md +++ b/src/ch14-02-publishing-to-crates-io.md @@ -1,6 +1,6 @@ ## 将 crate 发布到 Crates.io -> [ch14-02-publishing-to-crates-io.md](https://github.com/rust-lang/book/blob/master/src/ch14-02-publishing-to-crates-io.md) >
+> [ch14-02-publishing-to-crates-io.md](https://github.com/rust-lang/book/blob/master/src/ch14-02-publishing-to-crates-io.md)
> commit c084bdd9ee328e7e774df19882ccc139532e53d8 我们曾经在项目中使用 [crates.io](https://crates.io) 上的包作为依赖,不过你也可以通过发布自己的包来向它人分享代码。[crates.io](https://crates.io) 用来分发包的源代码,所以它主要托管开源代码。 @@ -111,17 +111,17 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ```rust,ignore //! # Art //! -//! 一个描述美术信息的库。 +//! A library for modeling artistic concepts. pub mod kinds { - /// 采用 RGB 色彩模式的主要颜色。 + /// The primary colors according to the RYB color model. pub enum PrimaryColor { Red, Yellow, Blue, } - /// 采用 RGB 色彩模式的次要颜色。 + /// The secondary colors according to the RYB color model. pub enum SecondaryColor { Orange, Green, @@ -132,8 +132,8 @@ pub mod kinds { pub mod utils { use crate::kinds::*; - /// 等量的混合两个主要颜色 - /// 来创建一个次要颜色。 + /// Combines two primary colors in equal amounts to create + /// a secondary color. pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor { // --snip-- # SecondaryColor::Orange @@ -178,7 +178,7 @@ fn main() { ```rust,ignore //! # Art //! -//! 一个描述美术信息的库。 +//! A library for modeling artistic concepts. pub use self::kinds::PrimaryColor; pub use self::kinds::SecondaryColor; diff --git a/src/ch15-01-box.md b/src/ch15-01-box.md index 9e55cde..44996fd 100644 --- a/src/ch15-01-box.md +++ b/src/ch15-01-box.md @@ -1,6 +1,6 @@ ## 使用`Box `指向堆上的数据 -> [ch15-01-box.md](https://github.com/rust-lang/book/blob/master/src/ch15-01-box.md) >
+> [ch15-01-box.md](https://github.com/rust-lang/book/blob/master/src/ch15-01-box.md)
> commit a203290c640a378453261948b3fee4c4c6eb3d0f 最简单直接的智能指针是 _box_,其类型是 `Box`。 box 允许你将一个值放在堆上而不是栈上。留在栈上的则是指向堆数据的指针。如果你想回顾一下栈与堆的区别请参考第四章。 diff --git a/src/ch15-02-deref.md b/src/ch15-02-deref.md index 960dae4..2458b0c 100644 --- a/src/ch15-02-deref.md +++ b/src/ch15-02-deref.md @@ -1,6 +1,6 @@ ## 通过 `Deref` trait 将智能指针当作常规引用处理 -> [ch15-02-deref.md](https://github.com/rust-lang/book/blob/master/src/ch15-02-deref.md) >
+> [ch15-02-deref.md](https://github.com/rust-lang/book/blob/master/src/ch15-02-deref.md)
> commit 44f1b71c117b0dcec7805eced0b95405167092f6 实现 `Deref` trait 允许我们重载 **解引用运算符**(_dereference operator_)`*`(与乘法运算符或通配符相区别)。通过这种方式实现 `Deref` trait 的智能指针可以被当作常规引用来对待,可以编写操作引用的代码并用于智能指针。 diff --git a/src/ch15-03-drop.md b/src/ch15-03-drop.md index d0930b5..249f712 100644 --- a/src/ch15-03-drop.md +++ b/src/ch15-03-drop.md @@ -1,6 +1,6 @@ ## 使用 `Drop` Trait 运行清理代码 -> [ch15-03-drop.md](https://github.com/rust-lang/book/blob/master/src/ch15-03-drop.md) >
+> [ch15-03-drop.md](https://github.com/rust-lang/book/blob/master/src/ch15-03-drop.md)
> commit 57adb83f69a69e20862d9e107b2a8bab95169b4c 对于智能指针模式来说第二个重要的 trait 是 `Drop`,其允许我们在值要离开作用域时执行一些代码。可以为任何类型提供 `Drop` trait 的实现,同时所指定的代码被用于释放类似于文件或网络连接的资源。我们在智能指针上下文中讨论 `Drop` 是因为其功能几乎总是用于实现智能指针。例如,`Box` 自定义了 `Drop` 用来释放 box 所指向的堆空间。 diff --git a/src/ch15-04-rc.md b/src/ch15-04-rc.md index feea295..3a49904 100644 --- a/src/ch15-04-rc.md +++ b/src/ch15-04-rc.md @@ -1,6 +1,6 @@ ## `Rc` 引用计数智能指针 -> [ch15-04-rc.md](https://github.com/rust-lang/book/blob/master/src/ch15-04-rc.md) >
+> [ch15-04-rc.md](https://github.com/rust-lang/book/blob/master/src/ch15-04-rc.md)
> commit 6f292c8439927b4c5b870dd4afd2bfc52cc4eccc 大部分情况下所有权是非常明确的:可以准确地知道哪个变量拥有某个值。然而,有些情况单个值可能会有多个所有者。例如,在图数据结构中,多个边可能指向相同的节点,而这个节点从概念上讲为所有指向它的边所拥有。节点直到没有任何边指向它之前都不应该被清理。 diff --git a/src/ch15-05-interior-mutability.md b/src/ch15-05-interior-mutability.md index 85be0b5..b37c05a 100644 --- a/src/ch15-05-interior-mutability.md +++ b/src/ch15-05-interior-mutability.md @@ -1,6 +1,6 @@ ## `RefCell` 和内部可变性模式 -> [ch15-05-interior-mutability.md](https://github.com/rust-lang/book/blob/master/src/ch15-05-interior-mutability.md) >
+> [ch15-05-interior-mutability.md](https://github.com/rust-lang/book/blob/master/src/ch15-05-interior-mutability.md)
> commit 26565efc3f62d9dacb7c2c6d0f5974360e459493 **内部可变性**(_Interior mutability_)是 Rust 中的一个设计模式,它允许你即使在有不可变引用时也可以改变数据,这通常是借用规则所不允许的。为了改变数据,该模式在数据结构中使用 `unsafe` 代码来模糊 Rust 通常的可变性和借用规则。我们还未讲到不安全代码;第十九章会学习它们。当可以确保代码在运行时会遵守借用规则,即使编译器不能保证的情况,可以选择使用那些运用内部可变性模式的类型。所涉及的 `unsafe` 代码将被封装进安全的 API 中,而外部类型仍然是不可变的。 diff --git a/src/ch15-06-reference-cycles.md b/src/ch15-06-reference-cycles.md index 494661a..af3ed8f 100644 --- a/src/ch15-06-reference-cycles.md +++ b/src/ch15-06-reference-cycles.md @@ -1,6 +1,6 @@ ## 引用循环与内存泄漏 -> [ch15-06-reference-cycles.md](https://github.com/rust-lang/book/blob/master/src/ch15-06-reference-cycles.md) >
+> [ch15-06-reference-cycles.md](https://github.com/rust-lang/book/blob/master/src/ch15-06-reference-cycles.md)
> commit f617d58c1a88dd2912739a041fd4725d127bf9fb Rust 的内存安全性保证使其难以意外地制造永远也不会被清理的内存(被称为 **内存泄漏**(_memory leak_)),但并不是不可能。与在编译时拒绝数据竞争不同, Rust 并不保证完全地避免内存泄漏,这意味着内存泄漏在 Rust 被认为是内存安全的。这一点可以通过 `Rc` 和 `RefCell` 看出:创建引用循环的可能性是存在的。这会造成内存泄漏,因为每一项的引用计数永远也到不了 0,其值也永远不会被丢弃。 diff --git a/src/ch16-00-concurrency.md b/src/ch16-00-concurrency.md index 152934f..cf02fbd 100644 --- a/src/ch16-00-concurrency.md +++ b/src/ch16-00-concurrency.md @@ -1,6 +1,6 @@ # 无畏并发 -> [ch16-00-concurrency.md](https://github.com/rust-lang/book/blob/master/src/ch16-00-concurrency.md) >
+> [ch16-00-concurrency.md](https://github.com/rust-lang/book/blob/master/src/ch16-00-concurrency.md)
> commit 1fedfc4b96c2017f64ecfcf41a0a07e2e815f24f 安全且高效的处理并发编程是 Rust 的另一个主要目标。**并发编程**(_Concurrent programming_),代表程序的不同部分相互独立的执行,而 **并行编程**(_parallel programming_)代表程序不同部分于同时执行,这两个概念随着计算机越来越多的利用多处理器的优势时显得愈发重要。由于历史原因,在此类上下文中编程一直是困难且容易出错的:Rust 希望能改变这一点。 diff --git a/src/ch16-01-threads.md b/src/ch16-01-threads.md index c253055..e3c184a 100644 --- a/src/ch16-01-threads.md +++ b/src/ch16-01-threads.md @@ -1,6 +1,6 @@ ## 使用线程同时运行代码 -> [ch16-01-threads.md](https://github.com/rust-lang/book/blob/master/src/ch16-01-threads.md) >
+> [ch16-01-threads.md](https://github.com/rust-lang/book/blob/master/src/ch16-01-threads.md)
> commit 1fedfc4b96c2017f64ecfcf41a0a07e2e815f24f 在大部分现代操作系统中,已执行程序的代码在一个 **进程**(_process_)中运行,操作系统则负责管理多个进程。在程序内部,也可以拥有多个同时运行的独立部分。运行这些独立部分的功能被称为 **线程**(_threads_)。 diff --git a/src/ch16-02-message-passing.md b/src/ch16-02-message-passing.md index 1525486..6069ac7 100644 --- a/src/ch16-02-message-passing.md +++ b/src/ch16-02-message-passing.md @@ -1,6 +1,6 @@ ## 使用消息传递在线程间传送数据 -> [ch16-02-message-passing.md](https://github.com/rust-lang/book/blob/master/src/ch16-02-message-passing.md) >
+> [ch16-02-message-passing.md](https://github.com/rust-lang/book/blob/master/src/ch16-02-message-passing.md)
> commit 26565efc3f62d9dacb7c2c6d0f5974360e459493 一个日益流行的确保安全并发的方式是 **消息传递**(_message passing_),这里线程或 actor 通过发送包含数据的消息来相互沟通。这个思想来源于 [Go 编程语言文档中](http://golang.org/doc/effective_go.html) 的口号:“不要通过共享内存来通讯;而是通过通讯来共享内存。”(“Do not communicate by sharing memory; instead, share memory by communicating.”) diff --git a/src/ch16-03-shared-state.md b/src/ch16-03-shared-state.md index a767e18..85703fe 100644 --- a/src/ch16-03-shared-state.md +++ b/src/ch16-03-shared-state.md @@ -1,6 +1,6 @@ ## 共享状态并发 -> [ch16-03-shared-state.md](https://github.com/rust-lang/book/blob/master/src/ch16-03-shared-state.md) >
+> [ch16-03-shared-state.md](https://github.com/rust-lang/book/blob/master/src/ch16-03-shared-state.md)
> commit ef072458f903775e91ea9e21356154bc57ee31da 虽然消息传递是一个很好的处理并发的方式,但并不是唯一一个。再一次思考一下 Go 编程语言文档中口号的这一部分:“不要通过共享内存来通讯”(“do not communicate by sharing memory.”): diff --git a/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/ch16-04-extensible-concurrency-sync-and-send.md index 97fedde..c84fbfe 100644 --- a/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -1,6 +1,6 @@ ## 使用 `Sync` 和 `Send` trait 的可扩展并发 -> [ch16-04-extensible-concurrency-sync-and-send.md](https://github.com/rust-lang/book/blob/master/src/ch16-04-extensible-concurrency-sync-and-send.md) >
+> [ch16-04-extensible-concurrency-sync-and-send.md](https://github.com/rust-lang/book/blob/master/src/ch16-04-extensible-concurrency-sync-and-send.md)
> commit 426f3e4ec17e539ae9905ba559411169d303a031 Rust 的并发模型中一个有趣的方面是:语言本身对并发知之 **甚少**。我们之前讨论的几乎所有内容,都属于标准库,而不是语言本身的内容。由于不需要语言提供并发相关的基础设施,并发方案不受标准库或语言所限:我们可以编写自己的或使用别人编写的并发功能。