Merge pull request #40 from murphil/murphy

Murphy
pull/44/head
KaiserY 7 years ago committed by GitHub
commit 6be944dce0

@ -4,22 +4,22 @@
> <br>
> commit 62f78bb3f7c222b574ff547d0161c2533691f9b4
欢迎阅读“Rust 程序设计语言”,一本关于 Rust 的介绍性书籍。Rust 是一个着用于安全、速度和并发的编程语言。它的设计不仅可以使程序获得性能和对底层语言的控制,并且能够享受高级语言强大的抽象能力。这些特性使得 Rust 适合那些有类似 C 语言经验并正在寻找一个更安全的替代者的程序员,同时也适合那些来自类似 Python 语言背景,正在探索在不牺牲表现力的情况下编写更好性能代码的开发者。
欢迎阅读“Rust 程序设计语言”,一本介绍 Rust 的书。Rust 是一门着眼于安全、速度和并发的编程语言。它的设计兼顾性能与底层控制,以及高级语言强大的抽象能力。适合那些有类 C 语言经验,正在寻找更安全的替代品的开发者;以及有着类 Python 语言背景,寻求在不牺牲表现力的前提下,编写性能更好的代码的开发者。
Rust 在编译时进行其绝大多数的安全检查和内存管理决策,因此程序的运行时性能没有受到影响。这让其在许多其他语言不擅长的应用场景中得以大显身手:存在可预测空间和时间要求的程序嵌入到其他语言中以及编写底层代码如设备驱动和操作系统。Rust 也很擅长 web 程序:它驱动着 Rust 包注册网站package
registry site[crates.io]!我们期待看到**你**使用 Rust 进行创作。
Rust 主要在编译时执行安全检查和内存管理决策,对运行时性能的影响微不足道。这使其在许多语言不擅长的应用场景中得以大显身手:空间和时间需求可预测的程序嵌入到其他语言中以及编写底层代码如设备驱动和操作系统。Rust 也很擅长 web 程序:它驱动着 Rust 包注册网站package
registry site[crates.io]!我们期待**你**使用 Rust 进行创作。
[crates.io]: https://crates.io/
本书是为已经至少了解一门编程语言的读者而写的。读完本书之后,你应该能自如的编写 Rust 程序。我们将通过小而集中并且相互依赖的例子来学习 Rust并向你展示如何使用 Rust 多样的功能,同时了解它们在幕后是如何执行的
本书的目标读者至少应了解一门其它编程语言。读完本书之后,你应该能自如的编写 Rust 程序。我们将通过短小精干、前后呼应的例子来学习 Rust并展示其多样功能的使用方法同时了解幕后如何运行
## 为本书做出贡献
本书是开源的。如果你发现任何错误,不要犹豫,[在 GitHub 上][on GitHub]发起 issue 或提交 pull request。请查看[CONTRIBUTING.md]获取更多信息。
本书是开源的。如果你发现任何错误,不要犹豫,[在 GitHub 上][on GitHub]发起 issue 或提交 pull request。请查看 [CONTRIBUTING.md] 获取更多信息。
[on GitHub]: https://github.com/rust-lang/book
[CONTRIBUTING.md]: https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md
> 译者注:这是本译本的 [GitHub 仓库][trpl-zh-cn],同样欢迎 Issue 和 PR :)
> 译者注:译本的 [GitHub 仓库][trpl-zh-cn],同样欢迎 Issue 和 PR :)
[trpl-zh-cn]: https://github.com/KaiserY/trpl-zh-cn

@ -4,40 +4,40 @@
> <br>
> commit c1b95a18dbcbb06aadf07c03759f27d88ccf62cf
使用 Rust 的第一步是安装。你需要网络连接来执行本章的命令,因为我们要从网上下载 Rust。
第一步是安装 Rust。你需要网络连接来执行本章的命令,因为我们要从网上下载 Rust。
我们将会展示很多使用终端的命令,并且这些代码都以`$`开头。并不需要真正输入`$`,它们在这里代表每行指令的开头。在网上会看到很多使用这个惯例的教程和例子:`$`代表以常规用户运行命令,`#`代表需要用管理员运行的命令。没有以`$`(或`#`的行通常是之前命令的输出。
我们将会展示很多在终端中输入的命令,这些命令均以 `$` 开头。你不需要真的输入`$`,在这里它代表每行命令的起始。网上有很多教程和例子遵循这种惯例:`$` 代表以常规用户身份运行命令,`#` 代表需要用管理员身份运行命令。没有以 `$`(或 `#`)起始的行通常是之前命令的输出。
### 在 Linux 或 Mac 上安装
如果你使用 Linux 或 Mac所有需要做的就是打开一个终端并输入:
如果你使用 Linux 或 Mac你需要做的全部,就是打开一个终端并输入:
```
$ curl https://sh.rustup.rs -sSf | sh
```
这会下载一个脚本并开始安装。你可能被提示要输入密码。如果一切顺利,将会出现如下内容:
这会下载一个脚本并开始安装。可能会提示你输入密码,如果一切顺利,将会出现如下内容:
```
Rust is installed now. Great!
```
当然,如果你不赞成`curl | sh`这种模式,可以随意下载、检查和运行这个脚本。
当然,如果你对于 `curl | sh` 心有疑虑,你可以随意下载、检查和运行这个脚本。
### 在 Windows 上安装
在 Windows 上,前往[https://rustup.rs](https://rustup.rs/)<!-- ignore -->并按照说明下载 rustup-init.exe。运行并遵循其提供的其余指示操作。
如果你使用 Windows前往 [https://rustup.rs](https://rustup.rs/)<!-- ignore -->,按说明下载 rustup-init.exe运行并照其指示操作。
本书其余 Windows 相关的命令假设你使用`cmd`作为你的 shell。如果你使用不同的 shell可能能够执行 Linux 和 Mac 用户相同的命令。如果都不行,请查看所使用的 shell 的文档。
本书中其余 Windows 相关的命令,假设你使用 `cmd` 作为 shell。如果你使用其它 shell也许可以执行与 Linux 和 Mac 用户相同的命令。如果不行,请查看该 shell 的文档。
### 自定义安装
如果有理由倾向于不使用 rustup.rs请查看[Rust 安装页面](https://www.rust-lang.org/install.html)获取其他选择。
无论出于何种理由,如果不愿意使用 rustup.rs请查看 [Rust 安装页面](https://www.rust-lang.org/install.html) 获取其他选择。
### 更新
一旦安装完 Rust更新到最新版本是简单的。在 shell 中运行更新脚本
一旦 Rust 安装完,更新到最新版本很简单。在 shell 中执行
```
$ rustup update
@ -45,7 +45,7 @@ $ rustup update
### 卸载
卸载 Rust 同安装一样简单。在 shell 中运行卸载脚本
卸载 Rust 同样简单。在 shell 中执行:
```
$ rustup self uninstall
@ -53,25 +53,25 @@ $ rustup self uninstall
### 故障排除
安装完 Rust 后,打开 shell输入
安装完 Rust 后,在 shell 中执行
```
$ rustc --version
```
应该能看到类似这样的版本号、提交 hash 和提交日期,对应你安装时的最新稳定版本
应该能看到类似这样的版本号、提交希和提交日期,对应安装时的最新稳定版
```
rustc x.y.z (abcabcabc yyyy-mm-dd)
```
如果出现这些内容Rust 就安装成功了!
出现这些内容Rust 就安装成功了!
恭喜入坑!(此处应该有掌声!)
如果有问题并且你在使用 Windows检查 Rustrustccargo 等)是否位于`%PATH%`系统变量中。
如果在 Windows 中使用出现问题,检查 Rustrustccargo 等)是否在 `%PATH%` 环境变量所包含的路径中。
如果还是不能运行,有许多可以获取帮助的地方。最简单的是 [irc.mozilla.org 上的 #rust IRC 频道][irc]<!-- ignore --> ,可以使用 [Mibbit][mibbit] 来访问它。访问这些地址然后就可以和其他能提供帮助的 Rustacean我们这些人自嘲的绰号聊天了。其它给力的资源包括[用户论坛][users]和 [Stack Overflow][stackoverflow]。
如果还是不能解决,有许多地方可以求助。最简单的是 [irc.mozilla.org 上的 #rust IRC 频道][irc]<!-- ignore --> ,可以使用 [Mibbit][mibbit] 来访问它。然后就能和其他 RustaceanRust 用户的称号,有自嘲意味)聊天并寻求帮助。其它给力的资源包括[用户论坛][users]和 [Stack Overflow][stackoverflow]。
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
@ -80,6 +80,6 @@ rustc x.y.z (abcabcabc yyyy-mm-dd)
### 本地文档
安装程序也包含一份本地文档的拷贝,你可以离线阅读它们。输入`rustup doc`将在浏览器中打开本地文档
安装程序自带本地文档,可以离线阅读。输入 `rustup doc` 可以在浏览器中查看
任何你不太确认标准库中提供的类型或函数是干什么的时候,请查看 API 文档!
任何时候,如果你拿不准标准库中类型或函数,请查看 API 文档!

@ -4,13 +4,13 @@
> <br>
> commit 4f2dc564851dc04b271a2260c834643dfd86c724
现在已经安装好了 Rust让我们来编写第一个 Rust 程序。当学习一门新语言的时候,编写一个在屏幕上打印 “Hello, world!” 文本的小程序是一个传统,而在这一部分将遵循这个传统。
Rust 已安好,让我们来编写第一个程序。当学习一门新语言的时候,使用该语言在屏幕上打印 “Hello, world!” 是一项传统,我们将遵循这个传统。
> 注意:本书假设你熟悉基本的命令行操作。Rust 本身并不对你的编辑器,工具和你的代码存放在何处有什么特定的要求,所以如果你比起命令行更喜欢 IDE请随意选择你喜欢的 IDE
> 注意:本书假设你熟悉基本的命令行操作。对于你的编辑器、工具以及你的代码存在何处Rust 并没有特殊要求,如果你更喜欢 IDE请随意
### 创建项目文件夹
首先,创建一个文件夹来存放 Rust 代码。Rust 并不关心你的代码存放在哪里,不过在本书中,我们建议在你的 home 目录创建一个 *projects* 目录,并把你的所有项目放在这。打开一个终端并输入如下命令来为这个项目创建一个文件夹:
首先,创建一个存放代码的文件夹。Rust 并不关心它的位置,不过在本书中,我们建议你在 home 目录中创建一个 *projects* 目录,并把你的所有项目放在这。打开一个终端,输入如下命令来创建一个文件夹:
Linux 和 Mac:
@ -32,9 +32,9 @@ Windows:
### 编写并运行 Rust 程序
接下来,新建一个叫做 *main.rs*源文件。Rust 文件总是以 *.rs* 后缀结尾。如果文件名多于一个单词,使用下划线分隔它们。例如,使用 *my_program.rs* 而不是 *myprogram.rs*
接下来,新建一个叫做 *main.rs*文件。Rust 源代码总是以 *.rs* 后缀结尾。如果文件名包含多个单词,使用下划线分隔它们。例如 *my_program.rs*而不是 *myprogram.rs*
现在打开刚创建的 *main.rs* 文件,输入如下代码:
现在打开刚创建的 *main.rs* 文件,输入如下代码:
<span class="filename">Filename: main.rs</span>
@ -52,11 +52,11 @@ $ ./main
Hello, world!
```
在 Windows 上,运行`.\main.exe`而不是`./main`。不管使用何种系统,你应该在终端看到`Hello, world!`字符串。如果你做到了,那么恭喜你!你已经正式编写了一个 Rust 程序。你是一名 Rust 程序员了!欢迎入坑。
在 Windows 上,运行 `.\main.exe`而不是`./main`。不管使用何种系统,你应该在终端看到 `Hello, world!` 字样。如果你做到了,恭喜你!你已经正式编写了一个 Rust 程序,成为一名 Rust 程序员!
### 分析 Rust 程序
现在让我们回过头来仔细看看“Hello, world!”程序到底发生了什么。这里是谜题的第一片:
现在,让我们回过头来仔细看看“Hello, world!”程序到底发生了什么。这是拼图的第一片:
```rust
fn main() {
@ -64,35 +64,35 @@ fn main() {
}
```
这几行定义了一个 Rust **函数**。`main`函数是特殊的:这是每一个可执行的 Rust 程序首先运行的函数(译者注:入口点)。第一行表示“定义一个叫 `main` 的函数,没有参数也没有返回值。”如果有参数的话,它们应该出现在括号中,`(`和`)`
这几行定义了一个 Rust **函数**。一个叫 `main` 的函数,没有参数也没有返回值。如果有参数的话,它们应该出现在括弧中,`(`和`)`之间。`main` 函数是特殊的:它是每一个可执行的 Rust 程序的入口点
同时注意函数体被包裹在大括号中,`{`和`}`。Rust 要求所有函数体都位于大括号中(译者注:对比有些语言特定情况可以省略大括号)。将前一个大括号与函数声明置于一行,并留有一个空格被认为是一个好的代码风格。
须注意函数体被包裹在花括号中,`{`和`}` 之间。所有函数体都要用花括号包裹起来(译者注:有些语言,当函数体只有一行时可以省略花括号,但 Rust 中是不行的)。一般来说,将左花括号与函数声明置于一行,并以空格分隔,是良好的代码风格。
在`main()`函数中:
`main()` 函数中:
```rust
println!("Hello, world!");
```
这行代码做了这个小程序的所有工作:它在屏幕上打印文本。这里有很多需要注意的细节。第一个是 Rust 代码风格使用 4 个空格缩进,而不是 1 个制表符tab
一行代码完成这个小程序的所有工作:在屏幕上打印文本。这里有很多细节需要注意。首先 Rust 使用 4 个空格的缩进风格,而不是 1 个制表符tab
第二个重要的部分是`println!()`。这叫做 Rust **宏**,是如何进行 Rust 元编程metaprogramming的关键所在。相反如果是调用一个函数的话它应该看起来像这样`println`(没有`!`)。我们将在 21 章 E 小节中更加详细的讨论 Rust 宏,不过现在你只需记住当看到符号`!`的时候,就代表在调用一个宏而不是一个普通的函数。
第二个重要的部分是`println!()`。这**宏**Rust 元编程metaprogramming的关键所在。而调用一个函数则要像这样`println`(没有`!`)。我们将在 21 章 E 小节中更加详细的讨论宏,现在你只需记住,当看到符号 `!` 的时候,调用的是宏而不是普通函数。
接下来,`"Hello, world!"` 是一个 **字符串**。我们把这个字符串作为一个参数传递给`println!`,它负责在屏幕上打印这个字符串。轻松加愉快!(⊙o⊙)
这一行以一个分号结尾(`;`)。`;`代表这个表达式的结束和下一个表达式的开始。大部分 Rust 代码行以`;`结尾。
该行以分号结尾(`;`)。`;` 代表一个表达式的结束和下一个表达式的开始。大部分 Rust 代码行以 `;` 结尾。
### 编译和运行是两个步骤
在“编写并运行 Rust 程序”部分,展示了如何运行一个新创建的程序。现在我们将拆分并检查每一步操作。
运行一个 Rust 程序之前,必须先编译它。可以输入`rustc`命令来使用 Rust 编译器并像这样传递源文件的名字
运行一个 Rust 程序之前,必须先编译它。可以通过 `rustc` 命令来使用 Rust 编译器,并传递源文件的名字给它,如下
```
$ rustc main.rs
```
如果你来自 C 或 C++ 背景,就会发现这与`gcc`和`clang`类似。编译成功后Rust 应该会输出一个二进制可执行文件,在 Linux 或 OSX 上在 shell 中你可以通过`ls`命令看到如下:
如果你有 C 或 C++ 背景,就会发现这与 `gcc``clang` 类似。编译成功后Rust 应该会输出一个二进制可执行文件,在 Linux 或 OSX 上在 shell 中你可以通过`ls`命令看到如下:
```
$ ls
@ -107,7 +107,7 @@ main.exe
main.rs
```
这表示我们有两个文件:*.rs* 后缀的源文件,和可执行文件(在 Windows下是 *main.exe*,其它平台是 *main*)。这里剩下的操作就只有运行 *main**main.exe* 文件,像这样:
这表示我们有两个文件:*.rs* 后缀的源文件,和可执行文件(在 Windows下是 *main.exe*,其它平台是 *main*)。然后运行 *main**main.exe* 文件,像这样:
```
$ ./main # or .\main.exe on Windows
@ -115,27 +115,27 @@ $ ./main # or .\main.exe on Windows
如果 *main.rs* 是我们的“Hello, world!”程序,它将会在终端上打印`Hello, world!`。
来自 Ruby、Python 或 JavaScript 这样的动态类型语言背景的同学,可能不太习惯在分开的步骤编译和执行程序。Rust 是一种 **静态提前编译语言***ahead-of-time compiled language*),这意味着可以编译好程序后,把它给任何人,他们不需要安装 Rust 就可运行。如果你给他们一个 `.rb` `.py``.js` 文件,他们需要先分别安装 RubyPythonJavaScript 实现运行时环境VM不过你只需要一句命令就可以编译和执行程序。这一切都是语言设计的权衡取舍。
来自 Ruby、Python 或 JavaScript 这样的动态类型语言背景的同学,可能不太习惯将编译和执行分为两个步骤。Rust 是一种 **预编译静态类型语言***ahead-of-time compiled language*),这意味着编译好程序后,把它给任何人,他们不需要安装 Rust 就可运行。如果你给他们一个 `.rb` `.py``.js` 文件,他们需要先分别安装 RubyPythonJavaScript 实现运行时环境VM不过你只需要一句命令就可以编译和执行程序。这一切都是语言设计的权衡取舍。
仅仅使用`rustc`编译简单程序是没问题的,不过随着项目的增长,你将想要能够控制你项目拥有的所有选项,并使其易于分享你的代码给别人或别的项目。接下来,我们将介绍一个叫做 Cargo 的工具,它将帮助你编写现实生活中的 Rust 程序。
使用 `rustc` 编译简单程序是没问题的,不过随着项目的增长,你将想要能够控制你项目的方方面面,并使其易于分享你的代码给别人或别的项目。接下来,我们将介绍一个叫做 Cargo 的工具,它将帮助你编写真实世界中的 Rust 程序。
## Hello, Cargo!
Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理他们的 Rust 项目,因为它使得很多任务变得更轻松。例如Cargo 负责构建代码、下载代码依赖库并编译这些库。我们把代码需要的库叫做 **依赖***dependencies*)。
Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理他们的 Rust 项目它使得很多任务变得更轻松。例如Cargo 负责构建代码、下载依赖库并编译。我们把代码需要的库叫做 **依赖***dependencies*)。
最简单的 Rust 程序,例如我们刚刚编写的,并没有任何依赖,所以目前我们只使用了 Cargo 负责构建代码的那一部分。随着编写更加复杂的 Rust 程序,你会想要添加依赖,如果你使用 Cargo 开始的话,这将会变得简单许多。
最简单的 Rust 程序,比如我们刚刚编写的,并没有任何依赖,所以我们只使用了 Cargo 构建代码的功能。随着更复杂程序的编写,你会想要添加依赖,如果你使用 Cargo 开始的话,这将会变得简单许多。
由于绝大部分 Rust 项目使用 Cargo本书接下来的部分将假设你使用它。如果使用安装章节介绍的官方安装包的话Rust 自带 Cargo。如果通过其他方式安装 Rust 的话,可以在终端输入如下命令检查是否安装了 Cargo
由于绝大部分 Rust 项目使用 Cargo本书接下来的部分将假设你使用它。如果使用之前介绍的官方安装包的话,它自带 Cargo。如果通过其他方式安装的话可以在终端输入如下命令检查是否安装了 Cargo
```
$ cargo --version
```
如果出现了版本号,一切 OK如果出现一个类似“`command not found`”的错误,那么你应该查看安装方式的文档来确定如何单独安装 Cargo。
如果出现了版本号,一切 OK如果出现类似“`command not found`”的错误,你应该查看安装文档以确定如何单独安装 Cargo。
### 使用 Cargo 创建项目
让我们使用 Cargo 来创建一个新项目看看与上面的`hello_world`项目有什么不同。回到 projects 目录(或者任何你决定放置代码的目录):
让我们使用 Cargo 来创建一个新项目,然后看看与上面的`hello_world`项目有什么不同。回到 projects 目录(或者任何你放置代码的目录):
Linux 和 Mac:
@ -156,11 +156,11 @@ $ cargo new hello_cargo --bin
$ cd hello_cargo
```
我们向`cargo new`传递了`--bin`因为我们的目标是生成一个可执行程序,而不是一个库。可执行文件是二进制可执行文件,通常就叫做 **二进制文件***binaries*)。项目的名称被定为`hello_cargo`,同时 Cargo 在一个同名目录中创建它的文件,接着我们可以进入查看。
我们向 `cargo new` 传递了 `--bin`因为我们的目标是生成一个可执行程序,而不是一个库。可执行程序是二进制可执行文件,通常就叫做 **二进制文件***binaries*)。项目的名称被定为`hello_cargo`,同时 Cargo 在一个同名目录中创建它的文件,接着我们可以进入查看。
如果列出 *hello_cargo* 目录中的文件,将会看到 Cargo 生成了一个文件和一个目录:一个 *Cargo.toml* 文件和一个 *src* 目录,*main.rs* 文件位于目录中。它也在 *hello_cargo* 目录初始化了一个 git 仓库,以及一个 *.gitignore* 文件;你可以改为使用不同的版本控制系统VCS或者不使用 VCS通过`--vcs`参数
如果列出 *hello_cargo* 目录中的文件,将会看到 Cargo 生成了一个文件和一个目录:一个 *Cargo.toml* 文件和一个 *src* 目录,*main.rs* 文件位于目录中。它也在 *hello_cargo* 目录初始化了一个 git 仓库,以及一个 *.gitignore* 文件;你可以通过`--vcs`参数切换到其它版本控制系统VCS或者不使用 VCS
使用你选择的文本编辑器IDE打开 *Cargo.toml* 文件。它应该看起来像这样:
使用文本编辑器IDE打开 *Cargo.toml* 文件。它应该看起来像这样:
<span class="filename">Filename: Cargo.toml</span>
@ -173,13 +173,13 @@ authors = ["Your Name <you@example.com>"]
[dependencies]
```
这个文件使用[*TOML*][toml]<!-- ignore --> (Tom's Obvious, Minimal Language) 格式。TOML 类似于 INI不过有一些额外的改进之处并且被用作 Cargo 的配置文件的格式。
这个文件使用 [*TOML*][toml]<!-- ignore --> (Tom's Obvious, Minimal Language) 格式。TOML 类似于 INI不过有一些额外的改进之处并且被用作 Cargo 的配置文件的格式。
[toml]: https://github.com/toml-lang/toml
第一行,`[package]`,是一个部分标题表明下面的语句用来配置一个包。随着我们在这个文件增加更多的信息,还将增加其他部分
第一行,`[package]`,是一个段落标题,表明下面的语句用来配置一个包。随着我们在这个文件增加更多的信息,还将增加其他段落
最后一行,`[dependencies]`,是列出项目依赖的 *crates*(我们这么称呼 Rust 代码包)的部分的开始,这样 Cargo 也就知道去下载和编译它们了。这个项目并不需要任何其他的 crate不过在下一章猜猜看教程会需要。
最后一行,`[dependencies]`,是项目依赖的 *crates*Rust 代码包)的段落的开始,这样 Cargo 就知道下载和编译它们了。这个项目并不需要任何其他的 crate不过在下一章猜猜看教程会需要。
现在看看 *src/main.rs*
@ -191,14 +191,14 @@ fn main() {
}
```
Cargo 为你生成了一个“Hello World!”,正如我们之前编写的那个!目前为止我们所见过的之前项目与 Cargo 生成的项目区别有:
Cargo 为你生成了一个“Hello World!”,正如我们之前编写的那个!目前为止,之前项目与 Cargo 生成项目区别有:
- 代码位于 *src* 目录
- 项目根目录包含一个 *Cargo.toml* 配置文件
Cargo 期望源文件位于 *src* 目录,这样将项目根目录留给 README、license 信息、配置文件和其他跟代码无关的文件。这样Cargo 帮助你保持项目干净整洁一切井井有条。
Cargo 期望源文件位于 *src* 目录,将项目根目录留给 README、license 信息、配置文件和其他跟代码无关的文件。这样Cargo 帮助你保持项目干净整洁一切井井有条。
如果没有使用 Cargo 开始项目,正如在 *hello_world* 目录中的项目,可以把它转化为一个使用 Cargo 的项目,通过将代码放入 *src* 目录并创建一个合适的 *Cargo.toml*
如果没有用 Cargo 创建项目,比如 *hello_world* 目录中的项目,可以通过将代码放入 *src* 目录并创建一个合适的 *Cargo.toml*,将其转化为一个 Cargo 项目
### 构建并运行 Cargo 项目
@ -218,7 +218,7 @@ Hello, world!
好的!如果一切顺利,`Hello, world!`应该再次打印在终端上。
第一次运行`cargo build`的时候也会使 Cargo 在项目根目录创建一个叫做 *Cargo.lock* 的新文件,它看起来像这样:
首次运行 `cargo build` 的时候Cargo 会在项目根目录创建一个新文件,*Cargo.lock*,它看起来像这样:
<span class="filename">Filename: Cargo.lock</span>
@ -228,9 +228,9 @@ name = "hello_cargo"
version = "0.1.0"
```
Cargo 使用 *Cargo.lock* 来记录程序的依赖。这个项目并没有依赖,所以内容有一点稀少。事实上,你自己永远也不需要碰这个文件;仅仅让 Cargo 处理它就行了。
Cargo 使用 *Cargo.lock* 来记录程序的依赖。这个项目并没有依赖,所以内容比较少。事实上,你自己永远也不需要碰这个文件,让 Cargo 处理它就行了。
我们刚刚使用`cargo build`构建了项目并使用`./target/debug/hello_cargo`运行了它,不过也可以使用`cargo run`编译并运行:
我们刚刚使用 `cargo build` 构建了项目并使用 `./target/debug/hello_cargo` 运行了它,也可以使用 `cargo run` 编译并运行:
```
$ cargo run
@ -238,7 +238,7 @@ $ cargo run
Hello, world!
```
注意这一次,并没有出现告诉我们 Cargo 正在编译 `hello_cargo` 的输出。Cargo 发现文件并没有被改变,所以只是运行了二进制文件。如果修改了源文件的话,将会出现像这样的输出:
注意这一次,并没有出现告诉我们 Cargo 正在编译 `hello_cargo` 的输出。Cargo 发现文件并没有被改变,直接运行了二进制文件。如果修改了源文件的话,将会出现像这样的输出:
```
$ cargo run
@ -247,12 +247,12 @@ $ cargo run
Hello, world!
```
所以现在又出现一些更多的不同:
所以现在又出现更多的不同:
- 使用`cargo build`构建项目(或使用`cargo run`一步构建并运行),而不是使用`rustc`
- 不同于将构建结果放在源码相同目录Cargo 会将它放到 *target/debug* 目录中的文件
- 使用 `cargo build` 构建项目(或使用 `cargo run` 一步构建并运行),而不是使用`rustc`
- 有别于将构建结果放在源码目录Cargo 将它放到 *target/debug* 目录
Cargo 的另一个优点是不管你使用什么操作系统它的命令都是一样的,所以之后我们将不再为 Linux 和 Mac 以及 Windows 提供特定的命令。
Cargo 的另一个优点是不管你使用什么操作系统它的命令都是一样的,所以之后我们将不再为 Linux 和 Mac 以及 Windows 提供相应的命令。
### 发布构建
@ -260,7 +260,7 @@ Cargo 的另一个优点是不管你使用什么操作系统它的命令都是
### 把 Cargo 当作习惯
对于简单项目, Cargo 并不能比`rustc`提供更多的价值,不过随着开发的进行终将体现它的价值。对于拥有多个 crate 的复杂项目,让 Cargo 来协调构建将更简单。有了 Cargo只需运行`cargo build`,然后一切将有序运行。即便这个项目很简单,现在也它使用了很多之后你的 Rust 程序生涯将会用得上的实用工具。事实上,无形中你可以使用下面的命令开始所有你想要从事的项目
对于简单项目, Cargo 并不能比`rustc`提供更多的价值,不过随着开发的进行终将体现它的价值。对于拥有多个 crate 的复杂项目,让 Cargo 来协调构建将更简单。有了 Cargo只需运行`cargo build`,然后一切将有序运行。即便这个项目很简单,也它使用了很多你之后的 Rust 生涯将会用得上的实用工具。其实你可以开始任何你想要从事的项目,使用下面的命令
```
$ git clone someurl.com/someproject
@ -268,6 +268,6 @@ $ cd someproject
$ cargo build
```
> 注意:如果你想要查看 Cargo 的更多细节,请阅读官方的 [Cargo guide],它覆盖了所有的功能。
> 注意:如果想要了解 Cargo 更多的细节,请阅读官方的 [Cargo guide],它覆盖了所有的功能。
[Cargo guide]: http://doc.crates.io/guide.html

@ -12,15 +12,15 @@ Rust 的并发模型中一个有趣的方面是:语言本身对并发知之**
`Send`标记 trait 表明类型的所有权可能被在线程间传递。几乎所有的 Rust 类型都是`Send`的,不过有一些例外。比如标准库中提供的 `Rc<T>`:如果克隆`Rc<T>`值,并尝试将克隆的所有权传递给另一个线程,这两个线程可能会同时更新引用计数。正如上一部分提到的,`Rc<T>`被实现为用于单线程场景,这时不需要为拥有线程安全的引用计数而付出性能代价。
因为`Rc<T>`没有标记为`Send`Rust 的类型系统和 trait bound 会确保我们不会错误的把一个`Rc<T>`值不安全的在线程间传递。列表 16-14 曾尝试这么做,不过得到了一个错误,`the trait Send is not implemented for Rc<Mutex<i32>>`。当切换为标记为`Send`的`Arc<T>`时,就没有问题了。
因为 `Rc<T>` 没有标记为 `Send`Rust 的类型系统和 trait bound 会确保我们不会错误的把一个 `Rc<T>` 值不安全的在线程间传递。列表 16-14 曾尝试这么做,不过得到了一个错误,`the trait Send is not implemented for Rc<Mutex<i32>>`。而使用标记为 `Send``Arc<T>` 时,就没有问题了。
任何完全由`Send`的类型组成的类型也会自动被标记为`Send`。几乎所有基本类型都是`Send`的,大部分标准库类型是`Send`的,除了`Rc<T>`以及第十九章将会讨论的裸指针raw pointer
任何完全由 `Send` 的类型组成的类型也会自动被标记为 `Send`:几乎所有基本类型都是 `Send` 的,大部分标准库类型是`Send`的,除了`Rc<T>`以及第十九章将会讨论的裸指针raw pointer
### `Sync`表明多线程访问是安全的
### `Sync` 表明多线程访问是安全的
`Sync`标记 trait 表明一个类型可以安全的在多个线程中拥有其值的引用。换一种方式来说就是,对于任意类型`T`,如果`&T``T`的引用)是`Send`的话`T`就是`Sync`的,这样其引用就可以安全的发送到另一个线程。类似于`Send`的情况,基本类型是`Sync`的,完全由`Sync`的类型组成的类型也是`Sync`的。
`Sync` 标记 trait 表明一个类型可以安全的在多个线程中拥有其值的引用。换一种方式来说,对于任意类型 `T`,如果`&T``T`的引用)是`Send`的话`T`就是`Sync`的,这样其引用就可以安全的发送到另一个线程。类似于 `Send` 的情况,基本类型是 `Sync` 的,完全由 `Sync` 的类型组成的类型也是 `Sync` 的。
`Rc<T>`也不是`Sync`的,出于其不是`Send`的相同的原因。`RefCell<T>`(第十五章讨论过)和`Cell<T>`系列类型不是`Sync`的。`RefCell<T>`在运行时所进行的借用检查也不是线程安全的。`Mutex<T>`是`Sync`的,正如上一部分所讲的它可以被用来在多线程中共享访问。
`Rc<T>` 也不是 `Sync` 的,出于其不是`Send`的相同的原因。`RefCell<T>`(第十五章讨论过)和`Cell<T>`系列类型不是`Sync`的。`RefCell<T>`在运行时所进行的借用检查也不是线程安全的。`Mutex<T>`是`Sync`的,正如上一部分所讲的它可以被用来在多线程中共享访问。
### 手动实现`Send`和`Sync`是不安全的

Loading…
Cancel
Save