pull/479/head
sunface 3 years ago
commit 24477bdd43

@ -4,10 +4,11 @@
- 官方: [https://course.rs](https://course.rs)
- 国内镜像: [https://book.rust.team](https://book.rust.team)
- 知乎: [支持章节内目录跳转,很好用!](https://www.zhihu.com/column/c_1452781034895446017)
- 配套练习题: [https://exercise.rs](https://github.com/sunface/rust-exercise)
- 最近修订: 2022-02-25 新增 [Cargo使用指南 - 依赖覆盖](https://zhuanlan.zhihu.com/p/472170018)
- QQ交流群1009730433
> Rust难上手来试试 [Rust By Practice](https://github.com/sunface/rust-practice),这里有最好的示例、练习题和应用实践。
## 教程简介
**`Rust语言圣经`**涵盖从**入门到精通**所需的 Rust 知识,目录及内容都经过深思熟虑的设计,同时语言生动幽默,行文流畅自如,摆脱技术书籍常有的机器味和晦涩感。
@ -35,11 +36,11 @@
非常感谢本教程的所有贡献者们,正是有了你们,才有了现在的高质量 Rust 教程!
- [@1132719438](https://github.com/1132719438)
- [@JesseAtSZ](https://github.com/JesseAtSZ)
- [@AllanDowney](https://github.com/AllanDowney)
- [@mg-chao](https://github.com/mg-chao)
- [@JesseAtSZ](https://github.com/JesseAtSZ)
- [@1132719438](https://github.com/1132719438)
- [@Mintnoii](https://github.com/Mintnoii)
- [@mg-chao](https://github.com/mg-chao)
- [@codemystery](https://github.com/codemystery)
尤其感谢这些主要贡献者,谢谢你们花费大量时间贡献了多处`fix`和高质量的内容优化。非常感动,再次感谢~~

@ -48,11 +48,11 @@
- [动态数组Vector](basic/collections/vector.md)
- [KV存储HashMap](basic/collections/hashmap.md)
- [类型转换](basic/converse.md)
- [返回值和异常](basic/result-error/intro.md)
- [返回值和错误处理](basic/result-error/intro.md)
- [panic深入剖析!](basic/result-error/panic.md)
- [返回值Result和?](basic/result-error/result.md)
- [包和模块](basic/crate-module/intro.md)
- [crate](basic/crate-module/crate.md)
- [Crate](basic/crate-module/crate.md)
- [模块Module](basic/crate-module/module.md)
- [使用use引入模块及受限可见性](basic/crate-module/use.md)
- [注释和文档](basic/comment.md)
@ -64,8 +64,8 @@
- [&'static 和 T: 'static](advance/lifetime/static.md)
<!-- - [一些关于生命周期的误解 todo](advance/lifetime/misconceptions.md) -->
- [函数式编程: 闭包、迭代器](advance/functional-programing/intro.md)
- [闭包closure](advance/functional-programing/closure.md)
- [迭代器iterator](advance/functional-programing/iterator.md)
- [闭包Closure](advance/functional-programing/closure.md)
- [迭代器Iterator](advance/functional-programing/iterator.md)
- [深入类型](advance/into-types/intro.md)
- [newtype 和 类型别名](advance/into-types/custom-type.md)
- [Sized 和不定长类型 DST](advance/into-types/sized.md)
@ -253,3 +253,4 @@
- [H-Rust更新版本列表](appendix/rust-versions/intro.md)
- [1.58](appendix/rust-versions/1.58.md)
- [1.59](appendix/rust-versions/1.59.md)

@ -1,5 +1,5 @@
# 错误处理
在之前的[返回值和错误章节](https://course.rs/basic/result-error/intro.html)中,我们学习了几个重要的概念,例如 `Result` 用于返回结果处理,`?` 用于错误的传播,若大家对此还较为模糊,强烈建议回头温习下。
在之前的[返回值和错误处理](https://course.rs/basic/result-error/intro.html)章节中,我们学习了几个重要的概念,例如 `Result` 用于返回结果处理,`?` 用于错误的传播,若大家对此还较为模糊,强烈建议回头温习下。
在本章节中一起来看看如何对 `Result` ( `Option` ) 做进一步的处理,以及如何定义自己的错误类型。

@ -150,7 +150,7 @@ error[E0597]: `s1` does not live long enough
| - `s1` dropped here while still borrowed
```
原因很简单,`s1` 得不够久,没有满足 `'static` 的生命周期要求。
原因很简单,`s1` 得不够久,没有满足 `'static` 的生命周期要求。
## 使用经验
至此,相信大家对于 `'static``T: 'static` 也有了清晰的理解,那么我们应该如何使用它们呢?

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

@ -1,11 +1,11 @@
# F-难点索引
# 附录 F难点索引
不可否认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
@ -23,9 +23,9 @@ fn main() {
}
```
通过`if`表达式将值赋予`var2`.
通过 `if` 表达式将值赋予 `var2`
你还可以在循环中结合`continue`、`break`来使用:`
你还可以在循环中结合 `continue` 、`break` 来使用:
```rust
let mut v = 0;
for i in 1..10 {

@ -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>
| 运算符 | 示例 | 解释 | 是否可重载 |
|----------|---------|-------------|---------------|
@ -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 模块

@ -3,23 +3,25 @@
## Rust 版本说明
早在第一章,我们见过 `cargo new`*Cargo.toml* 中增加了一些有关 `edition` 的元数据。本附录将解释其意义!
与其它语言相比Rust的更新迭代较为频繁(得益于精心设计过的发布流程以及Rust语言开发者团队管理)
与其它语言相比Rust 的更新迭代较为频繁(得益于精心设计过的发布流程以及 Rust 语言开发者团队管理):
- 每 6 周发布一个迭代版本
- 2-3年发布一个新的大版本Rust 2021 edtion, 每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。
- 2 - 3 年发布一个新的大版本:每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。
好处在于,可以满足不同的用户群体的需求:
- 对于活跃的 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 版本将能继续接收最新稳定版的改进。然而在一些情况,主要是增加了新关键字的时候,则可能出现了只能用于新版本的功能。只需切换版本即可利用新版本的功能。
@ -28,14 +30,13 @@
## Rust 自身开发流程
本附录介绍 Rust 语言自身是如何开发的以及这如何影响作为 Rust 开发者的你。
### 无停滞稳定
作为一个语言Rust **十分** 注重代码的稳定性。我们希望 Rust 成为你代码坚实的基础,假如持续地有东西在变,这个希望就实现不了。但与此同时,如果不能实验新功能的话,在发布之前我们又无法发现其中重大的缺陷,而一旦发布便再也没有修改的机会了。
对于这个问题我们的解决方案被称为 “无停滞稳定”“stability without stagnation”其指导性原则是无需担心升级到最新的稳定版 Rust。每次升级应该是无痛的并应带来新功能更少的 bug 和更快的编译速度。
对于这个问题我们的解决方案被称为 “无停滞稳定”“stability without stagnation”其指导性原则是无需担心升级到最新的稳定版 Rust。每次升级应该是无痛的并应带来新功能更少的 Bug 和更快的编译速度。
### Choo, Choo! ~~ 小火车发布流程启动
@ -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。
### 不稳定功能
@ -137,13 +138,13 @@ $ 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之后正如[不稳定功能](#不稳定功能) 部分所讨论的。

@ -1,6 +1,6 @@
# 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)
@ -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")
@ -76,5 +77,5 @@ zsh: segmentation fault cargo run
其实,还真有些用:
- 想要较小的可执行文件时(嵌入式wasm等)该方法就可以大显身手。因为panic会导致[二进制可执行文件变大不少](https://zhuanlan.zhihu.com/p/445465092)
- 它还可以提高一点性能, 因为编译器可能无法优化掉unwrap的指令分支 虽然它只会增加区区几条分支预测指令
- 想要较小的可执行文件时嵌入式WASM等该方法就可以大显身手。因为 `panic` 会导致[二进制可执行文件变大不少](https://zhuanlan.zhihu.com/p/445465092)
- 它还可以提高一点性能, 因为编译器可能无法优化掉 `unwrap` 的指令分支, 虽然它只会增加区区几条分支预测指令

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

@ -1,15 +1,15 @@
# 包和 Package
当读者按照章节顺序读到本章时,意味着你已经几乎具备了参与真实项目开发的能力。但是真实项目远比我们之前的 `cargo new` 的默认目录结构要复杂好在Rust 为我们提供了强大的包管理工具:
- **Package**:可以用来构建、测试和分享包
- **工作空间workspace**:对于大型项目,可以进一步将多个包联合在一起,组织成工作空间
- **包Crate**:一个由多个模块组成的树形结构,可以作为三方库进行分发,也可以生成可执行文件进行运行
- **模块Module**:可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
- **项目(Package)**:可以用来构建、测试和分享包
- **工作空间(WorkSpace)**:对于大型项目,可以进一步将多个包联合在一起,组织成工作空间
- **(Crate)**:一个由多个模块组成的树形结构,可以作为三方库进行分发,也可以生成可执行文件进行运行
- **模块(Module)**:可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
## 定义
其实 `Package` 和包 `crate` 很容易被搞混,甚至在很多书中,这两者都是不分的,但是由于官方对此做了明确的区分,因此我们会在本章节中试图(挣扎着)理清这个概念。
其实项目 `Package` 和包 `Crate` 很容易被搞混,甚至在很多书中,这两者都是不分的,但是由于官方对此做了明确的区分,因此我们会在本章节中试图(挣扎着)理清这个概念。
#### 包 crate
#### 包 Crate
对于 Rust 而言,包是一个独立的可编译单元,它编译后会生成一个可执行文件或者一个库。
一个包会将相关联的功能打包在一起,使得该功能可以很方便的在多个项目中分享。例如标准库中没有提供但是在三方库中提供的 `rand` 包,它提供了随机数生成的功能,我们只需要将该包通过 `use rand;` 引入到当前项目的作用域中,就可以在项目中使用 `rand` 的功能:`rand::XXX`。
@ -17,8 +17,8 @@
同一个包中不能有同名的类型,但是在不同包中就可以。例如,虽然 `rand` 包中,有一个 `Rng` 特征,可是我们依然可以在自己的项目中定义一个 `Rng`,前者通过 `rand::Rng` 访问,后者通过 `Rng` 访问,对于编译器而言,这两者的边界非常清晰,不会存在引用歧义。
## Package
鉴于 Rust 团队标新立异的起名传统,以及包的名称被 `crate` 占用,库的名称被 `library` 占用,因此导致我不知道该如何准确的翻译 `Package`,遂决定,不翻译,但是大家可以把它理解为一个项目工程,或者一个微服务工程
## 项目 Package
鉴于 Rust 团队标新立异的起名传统,以及包的名称被 `crate` 占用,库的名称被 `library` 占用,经过斟酌, 我们决定将 `Package` 翻译成项目,你也可以理解为工程、软件包
由于 `Package` 就是一个项目,因此它包含有独立的 `Cargo.toml` 文件,以及因为功能性被组织在一起的一个或多个包。一个 `Package` 只能包含**一个**库(library)类型的包,但是可以包含**多个**二进制可执行类型的包。
@ -34,12 +34,12 @@ $ ls my-project/src
main.rs
```
这里Cargo 为我们创建了一个名称是 `my-project``Package`,同时在其中创建了 `Cargo.toml` 文件,可以看一下该文件,里面并没有提到 `src/main.rs` 作为程序的入口,原因是 Cargo 有一个惯例:**src/main.rs是二进制包的根文件该二进制包的包名跟所属package相同在这里都是my-project**,所有的代码执行都从该文件中的 `fn main()` 函数开始。
这里Cargo 为我们创建了一个名称是 `my-project``Package`,同时在其中创建了 `Cargo.toml` 文件,可以看一下该文件,里面并没有提到 `src/main.rs` 作为程序的入口,原因是 Cargo 有一个惯例:**`src/main.rs` 是二进制包的根文件,该二进制包的包名跟所属 `Package` 相同,在这里都是 `my-project`**,所有的代码执行都从该文件中的 `fn main()` 函数开始。
使用 `cargo run` 可以运行该项目,输出:`Hello, world!`。
#### 库 Package
再来创建一个库类型的 `package`
再来创建一个库类型的 `Package`
```console
$ cargo new my-lib --lib
Created library `my-lib` package
@ -66,7 +66,7 @@ error: a bin target must be available for `cargo run`
#### 典型的 `Package` 结构
上面创建的 `Package` 中仅包含 `src/main.rs` 文件,意味着它仅包含一个二进制同名包 `my-project`。如果一个 `Package` 同时拥有 `src/main.rs``src/lib.rs`,那就意味着它包含两个包:库包和二进制包,这两个包名也都是 `my-project` —— 都与 `package` 同名。
上面创建的 `Package` 中仅包含 `src/main.rs` 文件,意味着它仅包含一个二进制同名包 `my-project`。如果一个 `Package` 同时拥有 `src/main.rs``src/lib.rs`,那就意味着它包含两个包:库包和二进制包,这两个包名也都是 `my-project` —— 都与 `Package` 同名。
一个真实项目中典型的 `Package`,会包含多个二进制包,这些包文件被放在 `src/bin` 目录下,每一个文件都是独立的二进制包,同时也会包含一个库包,该包只能存在一个 `src/lib.rs`
```css
@ -88,7 +88,7 @@ error: a bin target must be available for `cargo run`
```
- 唯一库包:`src/lib.rs`
- 默认二进制包:`src/main.rs`,编译后生成的可执行文件与`package`同名
- 默认二进制包:`src/main.rs`,编译后生成的可执行文件与 `Package` 同名
- 其余二进制包:`src/bin/main1.rs` 和 `src/bin/main2.rs`,它们会分别生成一个文件同名的二进制可执行文件
- 集成测试文件:`tests` 目录下
- 基准性能测试 `benchmark` 文件:`benches` 目录下

@ -9,8 +9,9 @@
同时,将大的代码文件拆分成包和模块,还允许我们实现代码抽象和复用:将你的代码封装好后提供给用户,那么用户只需要调用公共接口即可,无需知道内部该如何实现。
因此跟其它语言一样Rust 也提供了相应概念用于代码的组织管理:
- Packages一个 `Cargo` 提供的feature可以用来构建、测试和分享包
- 包Crate一个由多个模块组成的树形结构可以作为三方库进行分发也可以生成可执行文件进行运行
- 模块:可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
- 项目(Packages):一个 `Cargo` 提供的 `feature`,可以用来构建、测试和分享包
- 包(Crate):一个由多个模块组成的树形结构,可以作为三方库进行分发,也可以生成可执行文件进行运行
- 模块(Module):可以一个文件多个模块,也可以一个文件一个模块,模块可以被认为是真实项目中的代码组织单元
下面,让我们一一来学习这些概念以及如何在实践中运用。

@ -1,10 +1,10 @@
# 返回和错误处理
# 返回和错误处理
飞鸽传书、八百里加急,自古以来,掌权者最需要的就是及时获得对某个事物的信息反馈,在此过程中,也定义了相应的应急处理措施。
社会演变至今,这种思想依然没变,甚至来到计算中的微观世界,也是如此。及时、准确的获知系统在发生什么,是程序设计的重中之重。因此能够准确的分辨函数返回值是正确的还是错误的、以及在发生错误时该怎么快速处理,成了程序设计语言的必备功能。
Go 语言为人诟病的其中一点就是 ***if err != nil {}*** 的大量使用,缺乏一些程序设计的美感,不过我倒是觉得这种简单的方式也有其好处,就是阅读代码时的流畅感很强,你不需要过多的思考各种语法是什么意思。与 Go 语言不同Rust 博采众家之长,实现了颇具自身色彩的返回值和错误处理体系,本章我们就高屋建瓴地来学习,更加深入的讲解见[此章](../../advance/errors/intro.md).
Go 语言为人诟病的其中一点就是 ***if err != nil {}*** 的大量使用,缺乏一些程序设计的美感,不过我倒是觉得这种简单的方式也有其好处,就是阅读代码时的流畅感很强,你不需要过多的思考各种语法是什么意思。与 Go 语言不同Rust 博采众家之长,实现了颇具自身色彩的返回值和错误处理体系,本章我们就高屋建瓴地来学习,更加深入的讲解见[错误处理](https://course.rs/advance/errors.html)。
## Rust 的错误哲学
错误对于软件来说是不可避免的因此一门优秀的编程语言必须有其完整的错误处理哲学。在很多情况下Rust 需要你承认自己的代码可能会出错,并提前采取行动,来处理这些错误。

Loading…
Cancel
Save