pull/237/head
sunface 3 years ago
commit 5fad6e9690

@ -1,34 +1,38 @@
# Rust语言圣经(Rust course)
# Rust 语言圣经 (Rust course)
- 官方网址: https://course.rs
- 修订时间: **尚未发行**
- Rust版本 Rust edition 2021
- QQ交流群: 1009730433
- Rust 版本: Rust edition 2021
- QQ 交流群:1009730433
### 教程简介
`Rust语言圣经`涵盖从**入门到精通**所需的全部Rust知识目录及内容都经过深思熟虑的设计同时语言生动幽默行文流畅自如摆脱技术书籍常有的机器味和晦涩感。
`Rust 语言圣经`涵盖从**入门到精通**所需的全部 Rust 知识,目录及内容都经过深思熟虑的设计,同时语言生动幽默,行文流畅自如,摆脱技术书籍常有的机器味和晦涩感。
在Rust基础教学的同时我们还提供了
- **深入度**, 在基础教学的同时, 提供了深入剖析, 浅尝辄止并不能让我们站上紫禁之巅
- **性能优化**,选择Rust, 意味着就要追求性能, 因此你需要体系化的了解性能优化
- **专题**将Rust高级内容通过专题的方式一一呈现内容内聚性极强
Rust 基础教学的同时,我们还提供了:
- **深入度**,在基础教学的同时,提供了深入剖析,浅尝辄止并不能让我们站上紫禁之巅
- **性能优化**,选择 Rust意味着就要追求性能因此你需要体系化的了解性能优化
- **专题**,将 Rust 高级内容通过专题的方式一一呈现,内容内聚性极强
- **难点索引**,作为一本工具书,优秀的索引能力非常重要,遗忘不可怕,找不到才可怕
- **场景化模版**,程序员上网查询如何操作文件是常事,没有人能记住所有代码,场景化模版可解君忧
- **开源库推荐**, 根据场景推荐高质量的开源库降低Rust上手门槛
- **场景化模版**,程序员上网查询如何操作是常事,没有人能记住所有代码,场景化模版可解君忧
- **开源库推荐**, 根据场景推荐高质量的开源库,降低 Rust 上手门槛
总之在写作过程中我们始终铭记初心:为中国用户打造一本**全面的、深入的、持续更新的**Rust教程。 新手用来入门,老手用来提高,高手用来提升生产力。
总之在写作过程中我们始终铭记初心:为中国用户打造一本**全面的、深入的、持续更新的** Rust 教程。 新手用来入门,老手用来提高,高手用来提升生产力。
### 开源说明
Rust语言圣经是**完全开源**的电子书, 每个章节都至少用时4-6个小时才能初步完稿牺牲了大量休闲娱乐、陪伴家人的时间还没有任何钱赚**如果大家觉得这本书作者真的用心了,希望你能帮我们点一个`star`**,感激不尽:)
在开源版权上,我们选择了[No License](https://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwigkv-KtMT0AhXFdXAKHdI4BCcQFnoECAQQAw&url=https%3A%2F%2Fchoosealicense.com%2Fno-permission%2F&usg=AOvVaw3M2Q4IbdhnpJ2K71TF7SPB)这意味着读者可以随意的fork和阅读但是**不能私下修改后再包装分发**,如果有这方面的需求,请联系我们,我们不会收钱,只是希望知道谁通过什么方式分发了这本书的部分内容,望理解.
Rust 语言圣经是**完全开源**的电子书,每个章节都至少用时 4-6 个小时才能初步完稿,牺牲了大量休闲娱乐,陪伴家人的时间。而且还没有任何钱赚,**如果大家觉得这本书的作者真的用心了,希望你能帮我们点一个 🌟[star](https://github.com/sunface/rust-course)**,感激不尽!:)
在开源版权上,我们选择了 [No License](https://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwigkv-KtMT0AhXFdXAKHdI4BCcQFnoECAQQAw&url=https%3A%2F%2Fchoosealicense.com%2Fno-permission%2F&usg=AOvVaw3M2Q4IbdhnpJ2K71TF7SPB),这意味着**读者可以随意的 fork 和阅读,但是不能私下修改后再包装分发。**
如果有这方面的需求,请联系我们。我们不会收钱,只是希望知道谁通过什么方式分发了这本书的部分内容,望理解。
### Rust 社区
与国外的 Rust 发展如火如荼相比,国内的近况不是特别理想。导致目前这种状况的原因,我个人认为有以下几点:
### Rust社区
与国外的Rust发展如火如荼相比国内的近况不是特别理想。导致目前这种状况的原因我个人认为有以下几点原因
1. 上手难度大,学习曲线陡峭
2. 英文资料难学(阅读较难的技术内容,需要精准阅读,因此对外语能力要求较高),中文资料也不太好学(内容全面度、实时性,晦涩难懂等)
2. 英文资料难学(阅读较难的技术内容,需要精准阅读,因此对外语能力要求较高),中文资料也不太好学(内容全面度、实时性,晦涩难懂等)
3. 没有体系化的学习路线,新人往往扫完一遍入门书籍,就不知道何去何从
为此,我整了一本书和一个社区,欢迎大家的加入:
- QQ群1009730433
为此,我整了一本书和一个社区,欢迎大家的加入
- QQ 1009730433

@ -23,7 +23,7 @@ Rust使用一个相对传统的语法来创建整数(`1`,`2`,...)和浮点数(`1
| 128-位 | `i128` | `u128` |
| 视架构而定 | `isize` | `usize` |
类型定义的形式统一为:有无符号 + 类型大小(位数)。**无符号数**表示数字只能取正数,而**有符号**则表示数字即可以取正数又可以取负数。就像在纸上写数字一样:当要强调符号时,数字前面可以带上正号或负号;然而,当很明显确定数字为正数时,就不需要加上正号了。有符号数字以[二进制补码](https://en.wikipedia.org/wiki/Two%27s_complement)形式存储。
类型定义的形式统一为:有无符号 + 类型大小(位数)。**无符号数**表示数字只能取正数,而**有符号**则表示数字即可以取正数又可以取负数。就像在纸上写数字一样:当要强调符号时,数字前面可以带上正号或负号;然而,当很明显确定数字为正数时,就不需要加上正号了。有符号数字以[补码](https://en.wikipedia.org/wiki/Two%27s_complement)形式存储。
每个有符号类型规定的数字范围是 -(2<sup>n - 1</sup>) ~ 2<sup>n -
1</sup> - 1其中 `n` 是该定义形式的位长度。因此 `i8` 可存储数字范围是 -(2<sup>7</sup>) ~ 2<sup>7</sup> - 1即 -128 ~ 127。无符号类型可以存储的数字范围是 0 ~ 2<sup>n</sup> - 1所以 `u8` 能够存储的数字为 0 ~ 2<sup>8</sup> - 1即 0 ~ 255。
@ -48,11 +48,11 @@ Rust使用一个相对传统的语法来创建整数(`1`,`2`,...)和浮点数(`1
>
> 比方说有一个 `u8` ,它可以存放从 0 到 255 的值。那么当你将其修改为范围之外的值,比如 256则会发生**整型溢出**。关于这一行为 Rust 有一些有趣的规则:当在 debug 模式编译时Rust 会检查整型溢出,若存在这些问题,则使程序在编译时 *panic*(崩溃,Rust 使用这个术语来表明程序因错误而退出)。
>
> 在当使用 `--release` 参数进行 release 模式构建时Rust **不**检测溢出。相反当检测到整型溢出时Rust 会进行一种被称为二进制补码的方式进行(*twos complement wrapping*)操作。简而言之,大于该类型最大值的数值会被补码转换成该类型能够支持的对应数字的最小值。比如在 `u8` 的情况下256 变成 0257 变成 1依此类推。程序不会 panic但是该变量的值可能不是你期望的值。依赖整型溢出的行为不是一种正确的做法
> 在当使用 `--release` 参数进行 release 模式构建时Rust **不**检测溢出。相反当检测到整型溢出时Rust 会按照补码循环溢出(*twos complement wrapping*)的规则处理。简而言之,大于该类型最大值的数值会被补码转换成该类型能够支持的对应数字的最小值。比如在 `u8` 的情况下256 变成 0257 变成 1依此类推。程序不会 panic但是该变量的值可能不是你期望的值。依赖这种默认行为的代码都应该被认为是错误的代码
>
> 要显式处理溢出的可能性,可以使用标准库针对原始数字类型提供的以下的一系列方法:
> 要显式处理可能的溢出,可以使用标准库针对原始数字类型提供的这些方法:
>
> - 使用 `wrapping_*` 方法在所有模式下进行包裹,例如 `wrapping_add`
> - 使用 `wrapping_*` 方法在所有模式下都按照补码循环溢出规则处理,例如 `wrapping_add`
> - 如果使用 `checked_*` 方法时发生溢出,则返回 `None`
> - 使用 `overflowing_*` 方法返回该值和一个指示是否存在溢出的布尔值
> - 使用 `saturating_*` 方法使值达到最小值或最大值

@ -2,7 +2,7 @@
动态数组类型用`Vec<T>`表示,事实上,在之前的章节,它的身影多次出现,我们一直没有细讲,只是简单的把它当作数组处理。
动态数组允许你存储多个值,这些值在内存中一个紧挨着另一个排列,因此访问其中某个元素的成本非常低。动态数组只能存储相同类型的元素,如果你想存储不同类型的元素,可以使用之前讲过的枚举类型或者特征对象.
动态数组允许你存储多个值,这些值在内存中一个紧挨着另一个排列,因此访问其中某个元素的成本非常低。动态数组只能存储相同类型的元素,如果你想存储不同类型的元素,可以使用之前讲过的枚举类型或者特征对象
总之,当我们想拥有一个列表,里面都是相同类型的数据时,动态数组将会非常有用。
@ -10,41 +10,41 @@
在Rust中有多种方式可以创建动态数组。
#### Vec::new
使用`Vec::new`创建动态数组是最rusty的方式它调用了`Vec`中的`new`关联函数:
使用 `Vec::new` 创建动态数组是最 rusty 的方式,它调用了 `Vec` 中的 `new` 关联函数:
```rust
let v: Vec<i32> = Vec::new();
```
这里, `v`被显式地声明了类型`Vec<i32>`这是因为Rust编译器无法从`Vec::new()`中得到任何关于类型的暗示信息,因此也无法推导出`v`的具体类型,但是当你向里面增加一个元素后,一切又不同了:
这里`v` 被显式地声明了类型`Vec<i32>`,这是因为 Rust 编译器无法从 `Vec::new()` 中得到任何关于类型的暗示信息,因此也无法推导出 `v` 的具体类型,但是当你向里面增加一个元素后,一切又不同了:
```rust
let mut v = Vec::new();
v.push(1);
```
此时,`v`就无需手动声明类型,因为编译器通过`v.push(1)`,推测出`v`中的元素类型是`i32`,因此推导出`v`的类型是`Vec<i32>`.
此时,`v` 就无需手动声明类型,因为编译器通过 `v.push(1)`,推测出 `v` 中的元素类型是 `i32`,因此推导出 `v` 的类型是 `Vec<i32>`
> 如果预先知道要存储的元素个数,可以使用`Vec::with_capacity(capacity)`创建动态数组,这样可以避免因为插入大量新数据导致频繁的内存分配和拷贝,提升性能
> 如果预先知道要存储的元素个数,可以使用 `Vec::with_capacity(capacity)` 创建动态数组,这样可以避免因为插入大量新数据导致频繁的内存分配和拷贝,提升性能
#### vec![]
还可以使用宏`vec!`来创建数组,与`Vec::new`有所不同,前者能在创建同时给予初始化值:
还可以使用宏 `vec!` 来创建数组,与 `Vec::new` 有所不同,前者能在创建同时给予初始化值:
```rust
let v = vec![1, 2, 3];
```
同样,此处的`v`也无需标注类型,编译器只需检查它内部的元素即可自动推导出`v`的类型是`Vec<i32>`(Rust中整数默认类型是i32在[数值类型](../base-type/numbers.md#整数类型)中有详细介绍)。
同样,此处的 `v` 也无需标注类型,编译器只需检查它内部的元素即可自动推导出 `v` 的类型是 `Vec<i32>` (Rust中整数默认类型是i32在[数值类型](../base-type/numbers.md#整数类型)中有详细介绍)。
## 更新Vector
向数组尾部添加元素,可以使用`push`方法:
向数组尾部添加元素,可以使用 `push` 方法:
```rust
let mut v = Vec::new();
v.push(1);
```
与其它类型一样,必须将`v`声明为`mut`后,才能进行修改。
与其它类型一样,必须将 `v` 声明为 `mut` 后,才能进行修改。
## Vector与其元素共存亡
跟结构体一样,`Vector`类型在超出作用域范围后,会被自动删除:
跟结构体一样,`Vector` 类型在超出作用域范围后,会被自动删除
```rust
{
let v = vec![1, 2, 3];
@ -53,10 +53,10 @@ v.push(1);
} // <- v
```
当`Vector`被删除后,它内部存储的所有内容也会随之被删除。目前来看,这种解决方案简单直白,但是当`vector`中的元素被引用后,事情可能会没那么简单。
`Vector` 被删除后,它内部存储的所有内容也会随之被删除。目前来看,这种解决方案简单直白,但是当 `Vector` 中的元素被引用后,事情可能会没那么简单。
## 从Vector中读取元素
读取指定位置的元素有两种方式可选: 通过下标索引访问或者使用`get`方法:
读取指定位置的元素有两种方式可选:通过下标索引访问或者使用 `get` 方法:
```rust
let v = vec![1, 2, 3, 4, 5];
@ -69,10 +69,10 @@ match v.get(2) {
}
```
和其它语言一样,集合类型的索引下标都是从`0`开始,`&v[2]`表示借用`v`中的第三个元素,最终会获得该元素的引用。而`v.get(2)`也是访问第三个元素,但是有所不同的是,它返回了`Option<&T>`,因此还需要额外的`match`来匹配解构出具体的值。
和其它语言一样,集合类型的索引下标都是从 `0` 开始,`&v[2]` 表示借用 `v` 中的第三个元素,最终会获得该元素的引用。而 `v.get(2)` 也是访问第三个元素,但是有所不同的是,它返回了 `Option<&T>`,因此还需要额外的 `match` 来匹配解构出具体的值。
#### 下标索引与`.get`的区别
这两种方式都能成功的读取到指定的数组元素,既然如此为什么会存在两种方法?何况`.get`还会增加使用复杂度,让我们通过示例说明:
#### 下标索引与 `.get` 的区别
这两种方式都能成功的读取到指定的数组元素,既然如此为什么会存在两种方法?何况 `.get` 还会增加使用复杂度,让我们通过示例说明:
```rust
let v = vec![1, 2, 3, 4, 5];
@ -80,11 +80,11 @@ let does_not_exist = &v[100];
let does_not_exist = v.get(100);
```
运行以上代码,`&v[100]`的访问方式会导致程序无情报错退出,因为发生了数组越界访问。 但是`v.get`就不会,它在内部做了处理,有值的时候返回`Some(T)`,无值的时候返回`None`,因此`v.get`的使用方式非常安全。
运行以上代码,`&v[100]` 的访问方式会导致程序无情报错退出,因为发生了数组越界访问。 但是 `v.get` 就不会,它在内部做了处理,有值的时候返回 `Some(T)`,无值的时候返回 `None`,因此 `v.get` 的使用方式非常安全。
既然如此,为何不统一使用`v.get`的形式因为实在是有些啰嗦Rust语言的设计者和使用者在审美这方面还是相当统一的简洁即正义何况性能上也会有轻微的损耗。
既然如此,为何不统一使用 `v.get` 的形式因为实在是有些啰嗦Rust语言的设计者和使用者在审美这方面还是相当统一的简洁即正义何况性能上也会有轻微的损耗。
既然有两个选择,肯定就有如何选择的问题,答案很简单,当你确保索引不会越界的时候,就用索引访问,否则用`.get`。例如,访问第几个数组元素并不取决于我们,而是取决于用户的输入时,用`.get`会非常适合,天知道那些可爱的用户会输入一个什么样的数字进来!
既然有两个选择,肯定就有如何选择的问题,答案很简单,当你确保索引不会越界的时候,就用索引访问,否则用 `.get`。例如,访问第几个数组元素并不取决于我们,而是取决于用户的输入时,用 `.get` 会非常适合,天知道那些可爱的用户会输入一个什么样的数字进来!
##### 同时借用多个数组元素
既然涉及到借用数组元素,那么很可能会遇到同时借用多个数组元素的情况,还记得在[所有权和借用](../ownership/borrowing.md#借用规则总结)章节咱们讲过的借用规则嘛?如果记得,就来看看下面的代码:)
@ -98,9 +98,9 @@ v.push(6);
println!("The first element is: {}", first);
```
先不运行,来推断下结果,首先`first = &v[0]`进行了不可变借用,`v.push`进行了可变借用,如果`first`在`v.push`之后不再使用,那么该段代码可以成功编译(原因见[引用的作用域](../ownership/borrowing.md#可变引用与不可变引用不能同时存在)).
先不运行,来推断下结果,首先 `first = &v[0]` 进行了不可变借用,`v.push` 进行了可变借用,如果 `first` `v.push` 之后不再使用,那么该段代码可以成功编译(原因见[引用的作用域](../ownership/borrowing.md#可变引用与不可变引用不能同时存在))
可是上面的代码中,`first`这个不可变借用在可变借用`v.push`后被使用了,那么妥妥的,编译器就会报错:
可是上面的代码中,`first` 这个不可变借用在可变借用 `v.push` 后被使用了,那么妥妥的,编译器就会报错:
```console
$ cargo run
Compiling collections v0.1.0 (file:///projects/collections)
@ -122,15 +122,15 @@ error: could not compile `collections` due to previous error
其实,按理来说,这两个引用不应该互相影响的:一个是查询元素,一个是在数组尾部插入元素,完全不相干的操作,为何编译器要这么严格呢?
原因在于:数组的大小是可变的,当老数组的大小不够用时Rust会重新分配一块更大的内存空间然后把老数组拷贝过来。这种情况下之前的引用显然会指向一块无效的内存这非常rusty - 对用户进行严格的教育。
原因在于:数组的大小是可变的,当旧数组的大小不够用时Rust会重新分配一块更大的内存空间然后把旧数组拷贝过来。这种情况下之前的引用显然会指向一块无效的内存这非常rusty - 对用户进行严格的教育。
其实想想,**在长大之后,我们感激人生路上遇到过的严师益友,正是因为他们,我们才在正确的道路上不断前行,虽然在那个时候,并不能理解他们**而Rust就如那个良师益友它不断的在纠正我们不好的编程习惯直到某一天你发现自己能写出一次性通过的漂亮代码时就能明白它的良苦用心。
其实想想,**在长大之后,我们感激人生路上遇到过的严师益友,正是因为他们,我们才在正确的道路上不断前行,虽然在那个时候,并不能理解他们**,而 Rust 就如那个良师益友,它不断的在纠正我们不好的编程习惯,直到某一天,你发现自己能写出一次性通过的漂亮代码时,就能明白它的良苦用心。
> 若读者想要更深入的了解`Vec<T>`,可以看看[Rustonomicon],其中从零手撸一个动态数组,非常适合深入学习
## 迭代遍历Vector中的元素
如果想要依次访问数组中的元素,可以使用迭代的方式去遍历数组,这种方式比用下标的方式去遍历数组更安全也更高效(每次下标访问都会触发数组边界检查):
如果想要依次访问数组中的元素,可以使用迭代的方式去遍历数组,这种方式比用下标的方式去遍历数组更安全也更高效(每次下标访问都会触发数组边界检查)
```rust
let v = vec![1, 2, 3];
for i in &v {
@ -138,7 +138,7 @@ for i in &v {
}
```
也可以在迭代过程中,修改`Vector`中的元素:
也可以在迭代过程中,修改 `Vector` 中的元素:
```rust
let mut v = vec![1, 2, 3];
for i in &mut v {
@ -147,7 +147,7 @@ for i in &mut v {
```
## 存储不同类型的元素
在本节开头,有讲到数组的元素必需类型相同,但是也提到了解决方案: 那就是通过使用枚举类型和特征对象来实现不同类型元素的存储。先来看看通过枚举如何实现:
在本节开头,有讲到数组的元素必需类型相同,但是也提到了解决方案那就是通过使用枚举类型和特征对象来实现不同类型元素的存储。先来看看通过枚举如何实现:
```rust
#[derive(Debug)]
enum IpAddr {
@ -170,7 +170,7 @@ fn show_addr(ip: IpAddr) {
}
```
数组`v`中存储了两种不同的`ip`地址,但是这两种都属于`IpAddr`枚举类型的成员,因此可以存储在数组中。
数组 `v` 中存储了两种不同的 `ip` 地址,但是这两种都属于 `IpAddr` 枚举类型的成员,因此可以存储在数组中。
再来看看特征对象的实现:
```rust
@ -203,8 +203,8 @@ fn main() {
}
```
比枚举实现要稍微复杂一些,我们为`V4`和`V6`都实现了特征`IpAddr`,然后将它俩的实例用`Box::new`包裹后,存在了数组`v`中,需要注意的是,这里必需手动的指定类型:`Vec<Box<dyn IpAddr>>`,表示数组`v`存储的是特征`IpAddr`的对象,这样就实现了在数组中存储不同的类型.
比枚举实现要稍微复杂一些,我们为 `V4` `V6` 都实现了特征 `IpAddr`,然后将它俩的实例用 `Box::new` 包裹后,存在了数组 `v` 中,需要注意的是,这里必需手动的指定类型:`Vec<Box<dyn IpAddr>>`,表示数组 `v` 存储的是特征 `IpAddr` 的对象,这样就实现了在数组中存储不同的类型
在实际使用场景中,特征对象数组要比枚举数组常见很多,主要原因在于[特征对象非常灵活](../trait/trait-object.md),而编译器对枚举的限制较多,且无法动态增加类型。
最后,如果你想要了解`Vector`更多的用法,请参见本书的标准库解析章节:[`Vector`常用方法](../../std/vector.md)
最后,如果你想要了解 `Vector `更多的用法,请参见本书的标准库解析章节:[`Vector`常用方法](../../std/vector.md)

@ -1,16 +1,16 @@
# 返回和错误处理
飞鸽传书、八百里加急,自古以来,掌权者最需要的是及时获得对某个事物的信息反馈,在此过程中,也定义了相应的应急处理措施。
飞鸽传书、八百里加急,自古以来,掌权者最需要的是及时获得对某个事物的信息反馈,在此过程中,也定义了相应的应急处理措施。
社会演变至今,这种思想依然没变,甚至来到计算中的微观世界,也是如此。及时、准确的获知系统在发生什么,是程序设计的重中之重。因此能够准确的分辨函数返回值是正确的还是错误的、以及在发生错误时该怎么快速处理,成了程序设计语言的必备功能。
Go语言为人诟病的其中一点就是`if err != nil {}`的大量使用,缺乏一些程序设计的美感,不过我倒是觉得这种简单的方式也有其好处,就是阅读代码时的流畅感很强,你不需要过多的思考各种语法是什么意思。与Go语言不同Rust博采众家之长整出了颇具自身色彩的返回值和错误处理体系本章我们就从高屋建瓴的角度来学习,更加深入的讲解见[此章](../../errors/intro.md).
Go 语言为人诟病的其中一点就是 `if err != nil {}` 的大量使用,缺乏一些程序设计的美感,不过我倒是觉得这种简单的方式也有其好处,就是阅读代码时的流畅感很强,你不需要过多的思考各种语法是什么意思。与 Go 语言不同Rust 博采众家之长,实现了颇具自身色彩的返回值和错误处理体系,本章我们就高屋建瓴地来学习,更加深入的讲解见[此章](../../errors/intro.md).
## Rust的错误哲学
错误对于软件来说是不可避免的因此一门优秀的编程语言必须有其完整的错误处理哲学。在很多情况下Rust需要你承认自己的代码可能会出错并提前采取行动来处理这些错误。
错误对于软件来说是不可避免的因此一门优秀的编程语言必须有其完整的错误处理哲学。在很多情况下Rust 需要你承认自己的代码可能会出错,并提前采取行动,来处理这些错误。
Rust中的错误主要分为两类
- **可恢复错误**, 通常用于从系统全局角度来看可以接受的错误,例如处理用户的访问、操作等错误,这些错误只会影响某个用户自身的操作进程,而不会对系统的全局稳定性产生影响
- **不可恢复错误**,刚好相反,该错误通常是全局性或者系统性的错误,例如数组越界访问,系统启动时发生了影响启动流程的错误等等,这些错误的影响往往对于系统来说是致命的
Rust 中的错误主要分为两类:
- **可恢复错误**通常用于从系统全局角度来看可以接受的错误,例如处理用户的访问、操作等错误,这些错误只会影响某个用户自身的操作进程,而不会对系统的全局稳定性产生影响
- **不可恢复错误**刚好相反,该错误通常是全局性或者系统性的错误,例如数组越界访问,系统启动时发生了影响启动流程的错误等等,这些错误的影响往往对于系统来说是致命的
很多编程语言并不会区分这些错误而是直接采用异常的方式去处理。Rust没有异常但是Rust也有自己的卧龙凤雏`Result<T,E>`用于可恢复错误,`panic!`用于不可恢复错误。
很多编程语言并不会区分这些错误而是直接采用异常的方式去处理。Rust没有异常但是Rust也有自己的卧龙凤雏`Result<T,E>` 用于可恢复错误,`panic!` 用于不可恢复错误。

@ -7,5 +7,5 @@ String slice range indices must occur at valid UTF-8 character boundaries. If yo
>
> 比方说有一个 `u8` ,它可以存放从 0 到 255 的值。那么当你将其修改为范围之外的值,比如 256则会发生**整型溢出**。关于这一行为 Rust 有一些有趣的规则。当在 debug 模式编译时Rust 会检查整型溢出若存在这些问题则使程序在编译时 *panic*。Rust 使用这个术语来表明程序因错误而退出。 [该章节](../../errors/panic.md)会详细介绍 panic。
>
> 在当使用 `--release` 参数进行 release 模式构建时Rust **不**检测溢出。相反当检测到整型溢出时Rust 会进行一种被称为二进制补码的方式进行(*twos complement wrapping*)操作。简而言之,大于该类型最大值的数值会被补码转换成该类型能够支持的对应数字的最小值。比如在 `u8` 的情况下256 变成 0257 变成 1依此类推。程序不会 panic但是该变量的值可能不是你期望的值。依赖整型溢出包裹的行为不是一种正确的做法
> 在当使用 `--release` 参数进行 release 模式构建时Rust **不**检测溢出。相反当检测到整型溢出时Rust 会按照补码循环溢出(*twos complement wrapping*)的规则处理。简而言之,大于该类型最大值的数值会被补码转换成该类型能够支持的对应数字的最小值。比如在 `u8` 的情况下256 变成 0257 变成 1依此类推。程序不会 panic但是该变量的值可能不是你期望的值。依赖这种默认行为的代码都应该被认为是错误的代码
>

@ -1,135 +1,156 @@
# 进入Rust编程世界
# 进入 Rust 编程世界
## Rust发展历程
## Rust 发展历程
Rust 最早是 Mozilla 雇员 Graydon Hoare 的个人项目,从 2009 年开始,得到了 Mozilla 研究院的支助2010 年项目对外公布。2010 2011 年间实现自举。从此以后Rust在设计变化->崩溃的边缘反复横跳(历程极其艰辛),终于在 2015 年 5 月 15日发布1.0 版。在此研发过程中Rust 建立了一个强大且活跃社区形成了一整套完善稳定的项目贡献机制Rust能够飞速发展与这一点密不可分。Rust 现在由 [Rust项目开发者社区](https://github.com/rust-lang/rust)维护
Rust 最早是 Mozilla 雇员 Graydon Hoare 的个人项目。从 2009 年开始,得到了 Mozilla 研究院的资助。2010 年项目对外公布2010 2011 年间实现自举。从此以后Rust 在设计变化->崩溃的边缘反复横跳(历程极其艰辛)。终于,在 2015 年 5 月 15 日发布 1.0 版
大家可能疑惑Rust为啥用了这么久才到1.0版本与之相比Go语言2009年发布却在2012年仅用3年就发布了1.0版本。首先是因为Rust语言特性较为复杂因此需要全盘考虑的问题非常多其次Rust当时的参与者太多七嘴八舌的声音很多导致了众口难调而Rust开发团队又非常重视社区的意见 最后一旦1.0快速发布那么后续大部分语言特性就无法再修改对于有完美强迫症的Rust开发者团队来说某种程度上的不完美是不可接受的。因此Rust语言用了足足6年时间才发布了尽善尽美的1.0版本。
在此研发过程中Rust 建立了一个强大且活跃社区形成了一整套完善稳定的项目贡献机制Rust 能够飞速发展与这一点密不可分。Rust 现在由 [Rust 项目开发者社区](https://github.com/rust-lang/rust) 维护。
大家可能疑惑 Rust 为啥用了这么久才到 1.0 版本与之相比Go 语言 2009 年发布,却在 2012 年仅用 3 年就发布了 1.0 版本。
- 首先,因为 Rust 语言特性较为复杂,所以需要全盘考虑的问题非常多;
- 其次Rust 当时的参与者太多,七嘴八舌的声音很多,众口难调,而 Rust 开发团队又非常重视社区的意见;
- 最后,一旦 1.0 快速发布,那么后续大部分语言特性就无法再修改,对于有完美强迫症的 Rust 开发者团队来说,某种程度上的不完美是不可接受的。
因此Rust 语言用了足足 6 年时间,才发布了尽善尽美的 1.0 版本。
## 为何又来了一门新语言?
为何需要一个新语言简而言之因为还缺一门无GC、**性能高**、**工程性强**、语言级安全性以及能同时得到工程派和学院派认可的语言而Rust算是这样的语言。你也可以回忆下熟悉的语言看是不是有另外一门语言可以同时满足这些需求: )
而Rust最为人诟病的点也就一个学习曲线陡峭其实严格来说当语言生态起来后这个不算问题。
简而言之,因为还缺一门无 GC、性能高、工程性强、语言级安全性以及能同时得到工程派和学院派认可的语言而 Rust 算是这样的语言。你也可以回忆下熟悉的语言,看是不是有另外一门语言可以同时满足这些需求:)
Rust 最为人诟病的点,也就一个:学习曲线陡峭。不过其实严格来说,当语言生态起来后,这个不算问题。
### 缓解内卷
说Rust作为新语言会增加内卷其实恰恰相反Rust可以缓解内卷。为何不说C++内卷说Java、Python、JS内卷不就是后几个相对简单、上手容易嘛而Rust怎么看也是C++级别的上手难度OO
其实从我内心不可告人的角度出发并不希望Rust大众化因为这样可以保饭碗、保薪资还能更有行业内地位。但是从对Rust的喜爱角度出发我还是希望能卷一些但是。。。目前来看真的卷不动现在全世界范围Rust的需求都大于供给特别是优秀的Rust程序员更是难寻
有人说 Rust 作为新语言会增加内卷其实恰恰相反Rust 可以缓解内卷。为何不说 C++内卷,说 Java、Python、JS 内卷?不就是后几个相对简单、上手容易嘛?而 Rust 怎么看也是 C++ 级别的上手难度
与Go语言相比一个优秀的Rust程序员所需的门槛高得多例如融汇贯通Rust语言各种中高级特性、闭着眼睛躺过各种坑、不用回忆无需查找就能立刻写出最合适的包/模块/方法、性能/安全/工程性的权衡选择信手拈来、深层性能优化易如反掌、异步编程小菜一碟更别说Rust之外的操作系统、网络、算法等等相关知识
其实从我内心不可告人的角度出发,并不希望 Rust 大众化,因为这样可以保饭碗、保薪资,还能更有行业内地位。但是从对 Rust 的喜爱角度出发,我还是希望能卷一些。但是,目前来看真的卷不动,现在全世界范围内 Rust 的需求都大于供给,特别是优秀的 Rust 程序员更是难寻
所以Rust可以缓解内卷而不是增加内卷可以说是程序员的福音不再是被随意替换的螺丝钉。
与 Go 语言相比,成为一个优秀的 Rust 程序员所需的门槛高得多,例如融汇贯通 Rust 语言各种中高级特性、闭着眼睛躺过各种坑、不用回忆无需查找就能立刻写出最合适的包/模块/方法、性能/安全/工程性的权衡选择信手拈来、深层性能优化易如反掌、异步编程小菜一碟,更别说 Rust 之外的操作系统、网络、算法等等相关知识。
所以Rust 可以缓解内卷,而不是增加内卷。可以说是程序员的福音,不再是被随意替换的螺丝钉。
### 效率
下面从三个角度来谈谈Rust的效率学习、运行、开发。
下面从三个角度来谈谈 Rust 的效率:学习、运行、开发。
#### 学习效率
众所周知Rust学习曲线陡峭最初我对此说法还嗤之以鼻随着不断的深入我现在也很认可这个说法。Rust之难不在于语言特性这些都可以很容易学到而在于:
众所周知Rust 学习曲线陡峭。最初我对此说法还嗤之以鼻随着不断的深入我现在也很认可这个说法。Rust 之难,不在于语言特性,这些都可以很容易学到,而在于:
- 实践中如何融会贯通的运用
- 遇到了坑时(生命周期、借用错误,自引用等)如何迅速、正确的解决
- 遇到了坑时(生命周期、借用错误,自引用等)如何迅速、正确的解决
- 大量的标准库方法记忆及熟练使用,这些是保证开发效率的关键
- 心智负担较重,特别是初中级阶段
- 心智负担较重,特别是初中级阶段
好在,针对这些,目前国内有了一门非常全面的[Rust学习教程](https://github.com/sunface/rust-course)(非官方那本书)可以有效降低Rust的学习和使用门槛。
好在,针对这些,目前国内有了一门非常全面的 [Rust 学习教程](https://github.com/sunface/rust-course)(非官方那本书),可以有效降低 Rust 的学习和使用门槛。
#### 运行效率
得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和三方库实现Rust具备非常优秀的性能和C语言、C++是[一个级别](https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/rust.html)。
同时Rust有一个极大的好处只要按照正确的方式使用Rust无需性能优化就能实现非常优秀的表现不可谓不惊艳
得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和三方库实现Rust 具备非常优秀的性能,和 C、C++ 是 [一个级别](https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/rust.html)。
同时 Rust 有一个极大的好处:只要按照正确的方式使用 Rust无需性能优化就能实现非常优秀的表现不可谓不惊艳
现在有不少用Rust重写的工具、平台都超过了原来用C、C++实现的版本,将老前辈拍死在沙滩上,俨然成为一种潮流~~
现在有不少用 Rust 重写的工具、平台都超过了原来用 C、C++ 实现的版本,将老前辈拍死在沙滩上,俨然成为一种潮流~~
#### 开发效率
Rust的开发效率可以先抑后扬来形容在刚开始上手写项目时你的开发速度将显著慢于go、java等语言一旦开始熟悉标准库常用的方法开发效率将大幅提升甚至当形成肌肉记忆后开发效率将不会慢于这些语言而且原生就能写出高质量、安全、高效的代码可以说中高级级Rust程序员就是高效程序员的代名词。
Rust 的开发效率可以先抑后扬来形容。在刚开始上手写项目时,你的开发速度将显著慢于 go、java 等语言,不过,一旦开始熟悉标准库常用的方法,开发效率将大幅提升,甚至当形成肌肉记忆后,开发效率将不会慢于这些语言,而且原生就能写出高质量、安全、高效的代码,可以说中高级 Rust 程序员就是高效程序员的代名词。
### 个人的好处
学习Rust对个人也有极大的好处。
学习 Rust 对个人也有极大的好处。
#### 成为更好的程序员
要学好Rust你需要深入理解内存、堆栈、引用、变量作用域这些其它高级语言往往不会深入接触的内容同时Rust会通过语法、编译器和clippy这些静态检查工具半帮助半强迫的让你成为更优秀的程序员写出更好的代码。
同时当你掌握了Rust你自发性的就会想要去做一些更偏底层的事情这些都可以帮助你更加了解操作系统、网络、性能优化等底层知识也会间接或者直接的接触到各种算法、数据结构实现。
要学好 Rust你需要深入理解内存、堆栈、引用、变量作用域等这些其它高级语言往往不会深入接触的内容。另外Rust 会通过语法、编译器和 clippy 这些静态检查工具半帮助半强迫的让你成为更优秀的程序员,写出更好的代码。
同时,当你掌握了 Rust你就会自发性的想要去做一些更偏底层的事情这些都可以帮助你更加了解操作系统、网络、性能优化等底层知识也会间接或者直接的接触到各种算法和数据结构的实现。
慢慢的,你就在成为那个更好的程序员,也是更优秀的自己。
#### 增加不可替代性
语言难学也有好处一旦掌握你将具备较强的不可替代性不再是一个简单的工具人角色。看看现在内卷严重的Java工具人有多少一个人离职另外一个人很快就能替补上。
当然我不是说Rust会给公司带来这种隐形的维护成本毕竟这其实是一种双赢公司收获了更优秀的程序员(不可否认的是Rust程序员普遍确实水平更高毕竟都是有很好的其它语言基础、也很有追求的自驱性人才),而你也收获了更稳定的工作环境甚至是更高的收入。
语言难学,也有好处。一旦掌握,你将具备较强的不可替代性,不再是一个简单的工具人角色。看看现在内卷严重的 Java工具人有多少一个人离职另外一个人很快就能替补上。
当然,我不是说 Rust 会给公司带来这种隐形的维护成本,毕竟这其实是一种双赢,公司收获了更优秀的程序员(不可否认的是 Rust 程序员普遍确实水平更高,毕竟都是有很好的其它语言基础、也很有追求的自驱型人才),而你也收获了更稳定的工作环境,甚至是更高的收入。
### 团队的好处
先不说安全、可靠性等对公司团队非常友好的特性就说Rust程序只要能跑起来那代码质量其实就是相当不错的因为Rust编译器、clippy啥的实在是严师厉友甚至有些鸡毛。
正因为这较高的质量下限我们在review时并不用担心潜在的各种坑因此可以实现快速的开发、review、merge流程。
先不说安全、可靠性等对公司团队非常友好的特性,就说 Rust 程序只要能跑起来,那代码质量其实就是相当不错的,因为 Rust 编译器、clippy 啥的实在是严师厉友,甚至有些鸡毛。
正因为这较高的质量下限,我们在 review 时并不用担心潜在的各种坑因此可以实现快速的开发、review、merge 流程。
而且由于Rust语言拥有异常强大的编译器和语言特性因此Rust的代码天然就会比其它语言有更少的Bug同时Rust拥有非常完善的工具链、最好的包管理工具这些叠加在一起决定了Rust非常适合大型开发者团队的协作开发。
而且由于 Rust 语言拥有异常强大的编译器和语言特性,因此 Rust 的代码天然就会比其它语言有更少的 Bug。同时 Rust 拥有非常完善的工具链,最好的包管理工具,这些叠加在一起,决定了 Rust 非常适合大型开发者团队的协作开发。
也许Rust在开发速度上不是最快的但是从开发 + 维护的角度来看,这个成本绝对是各个语言中最小的之一,当然如果你的公司就追求做出来能用就行那Rust确实有些灰姑娘的感觉。
也许 Rust 在开发速度上不是最快的,但是从开发 + 维护的角度来看,这个成本在各个语言中绝对是很小的。当然,如果你的公司就追求做出来能用就行,那 Rust 确实有些灰姑娘的感觉。
还有一点很重要现在的Rust程序员往往拥有超出更出众的能力和学习自驱性,因此团队招到的人天然就保持了较高的底线如果你有幸招到一个优秀的Rust程序员那真是捡到宝了他也会同时带动周围的人一起慢慢优秀(优秀的Rust程序员较好辨别门槛低的语言就并没有那么好辨别)。总之,一个这样的程序员会给团队带来远超他薪资的潜在回报和长远收益。
还有一点很重要,现在的 Rust 程序员往往拥有更出众的能力和学习自驱性,因此团队招到的人天然就保持了较高的底线。如果你有幸招到一个优秀的 Rust 程序员,那真是捡到宝了,他也会同时带动周围的人一起慢慢优秀(优秀的 Rust 程序员比较好辨别,门槛低的语言就并没有那么好辨别)。总之,一个这样的程序员会给团队带来远超他薪资的潜在回报和长远收益。
### 开源
目前Rust的主战场是在开源上Go的成功也证明了农村包围城市的可行性。
- UI层开发Rust的WASM发展的如火如荼, 隐隐有王者风范在JS的基础设施领域Rust也是如鱼得水, 例如`swc`、`deno`等,同时`nextjs`也是押宝Rust可以说Rust在前端的成功完全是无心插柳柳成荫。
- 基础设施层, 数据库、搜索引擎、网络设施、云原生等都在出现Rust的身影而且还不少
- 系统开发目前linux已经将Rust列为即将支持的内核开发语言是即C语言后第二门支持内核开发的语言不过刚开始将主要支持驱动开发
- 系统工具现在最流行的就是用Rust重写之前C、C++写的一票系统工具,还都获得了挺高的关注和很好的效果, 例如 sd, exa, ripgrep, fd, bat等
- 操作系统, Rust在开发的操作系统现在有好几个其中最有名的可能就是谷歌的fushia, Rust在其中扮演非常重要的角色
- 区块链目前Rust和Go可以说各领风骚未来Rust可能会一统江湖
目前 Rust 的主战场是在开源上Go 的成功也证明了农村包围城市的可行性。
类似的还有很多,我们就不一一列举, 总之现在有大量的项目在被用Rust重写同时还有海量的项目在等待被重写这些都是赚取star和认可的好机会在其它语言杀成一片红海时Rust还留了一大片蓝海等待大家的探索!
- UI 层开发Rust 的 WASM 发展的如火如荼,隐隐有王者风范,在 JS 的基础设施领域Rust 也是如鱼得水,例如`swc`、`deno`等。同时`nextjs`也是押宝 Rust可以说 Rust 在前端的成功完全是无心插柳柳成荫。
- 基础设施层,数据库、搜索引擎、网络设施、云原生等都在出现 Rust 的身影,而且还不少。
- 系统开发,目前 linux 已经将 Rust 列为即将支持的内核开发语言,是既 C 语言后第二门支持内核开发的语言,不过刚开始将主要支持驱动开发。
- 系统工具,现在最流行的就是用 Rust 重写之前 C、C++ 写的一票系统工具,还都获得了挺高的关注和很好的效果,例如 sd, exa, ripgrep, fd, bat 等。
- 操作系统,现在在使用 Rust 开发的操作系统有好几个,其中最有名的可能就是谷歌的 FuchsiaRust 在其中扮演非常重要的角色
- 区块链,目前 Rust 和 Go 可以说各领风骚,未来 Rust 可能会一统江湖
类似的还有很多,我们就不一一列举。总之,现在有大量的项目在被用 Rust 重写,同时还有海量的项目在等待被重写,这些都是赚取 star 和认可的好机会。在其它语言杀成一片红海时Rust 还留了一大片蓝海等待大家的探索!
### 相比其他语言 Rust 的优势
### 相比其他语言Rust的优势
由于篇幅有限我们这里不会讲述详细的对比就是简单介绍下Rust的优势。因此并不是说Rust就优于这些语言大家轻喷:)
由于篇幅有限,我们这里不会讲述详细的对比,就是简单介绍下 Rust 的优势。并不是说 Rust 就优于这些语言,大家轻喷:)
#### Go
Rust语言表达能力更强性能更高同时线程安全方面Rust也更强不容易写出错误的代码包管理Rust也更好Go虽然在1.10版本后提供了包管理但是目前还比不上Rust的。
Rust 语言表达能力更强,性能更高。同时线程安全方面 Rust 也更强,不容易写出错误的代码。包管理 Rust 也更好Go 虽然在 1.10 版本后提供了包管理,但是目前还比不上 Rust 的。
#### C++
与C++相比Rust的性能相差无几但是在安全性方面会更优特别是使用第三方库时Rust的严格要求会让第三方库的质量明显高很多。
语言本身的学习Rust的前中期学习曲线会更陡峭但是对于未来使用场景和生态的学习,C++会更难、更复杂。
与 C++ 相比Rust 的性能相差无几但是在安全性方面会更优特别是使用第三方库时Rust 的严格要求会让第三方库的质量明显高很多。
语言本身的学习Rust 的前中期学习曲线会更陡峭但是对于未来使用场景和生态的学习C++ 会更难,更复杂。
#### Java
除了极少部分纯粹的数字计算性能Rust的性能是全面领先于Java的同时Rust占用内存小的多因此实现同等规模的服务Rust所需的硬件成本会显著降低。
除了极少部分纯粹的数字计算性能Rust 的性能是全面领先于 Java 的。同时 Rust 占用内存小的多因此实现同等规模的服务Rust 所需的硬件成本会显著降低。
#### Python
性能自然是Rust完胜同时Rust对运行环境要求较低这两点差不多就足够抉择了因为python和rust的彼此适用面其实不太冲突。
性能自然是 Rust 完胜,同时 Rust 对运行环境要求较低,这两点差不多就足够抉择了。不过 python 和 rust 的彼此适用面其实也不太冲突。
### 使用现状
- AWS从2017年开始就用Rust实现了无服务器计算平台 AWS Lambda 和 AWS Fargate, 并且用Rust重写了Bottlerocket OS和AWS Nitro系统这两个是弹性计算云(EC2)的重要服务
- Cloudflare是Rust的重度用户DNS、无服务计算、网络包监控等基础设施都都与Rust密不可分
- Dropbox的底层存储服务完全由Rust重写达到了数万PB的规模
- Google除了在安卓系统的部分模块中使用Rust外还在它最新的操作系统fuchsia中重度使用Rust
- Facebook使用Rust来增强自己的网页端、移动端和API服务的性能同时还写了Hack编程语言的虚拟机
- Microsoft使用Rust为Azure平台提供一些组件其中包括IoT的核心服务
- Github和npmjs.com使用Rust提供高达每天13亿次的npm包下载
- Rust目前已经成为全世界区块链平台的首选开发语言
- AWS 2017 年开始就用 Rust 实现了无服务器计算平台: AWS Lambda 和 AWS Fargate,并且用 Rust 重写了 Bottlerocket OS 和 AWS Nitro 系统,这两个是弹性计算云 (EC2) 的重要服务
- Cloudflare Rust 的重度用户DNS、无服务计算、网络包监控等基础设施都都与 Rust 密不可分
- Dropbox 的底层存储服务完全由 Rust 重写,达到了数万 PB 的规模
- Google 除了在安卓系统的部分模块中使用 Rust 外,还在它最新的操作系统 Fuchsia 中重度使用 Rust
- Facebook 使用 Rust 来增强自己的网页端、移动端和 API 服务的性能,同时还写了 Hack 编程语言的虚拟机
- Microsoft 使用 Rust Azure 平台提供一些组件,其中包括 IoT 的核心服务
- Github npmjs.com使用 Rust 提供高达每天 13 亿次的 npm 包下载
- Rust 目前已经成为全世界区块链平台的首选开发语言
- Tidb国内最有名的开源分布式数据库
尤其值得一提的是AWS实际上在押宝Rust未来对Rust的使用可能很快会上升到**first-class**的地位。
尤其值得一提的是AWS 实际上在押宝 Rust未来对 Rust 的使用可能很快会上升到 **first-class** 的地位。
## Rust语言版本更新
## Rust 语言版本更新
与其它语言相比Rust的更新迭代较为频繁(得益于精心设计过的发布流程以及Rust语言开发者团队的严格管理)
- 每6周发布一个迭代版本
- 2-3年发布一个新的大版本Rust 2018 editionRust 2021 edtion
与其它语言相比Rust 的更新迭代较为频繁(得益于精心设计过的发布流程以及 Rust 语言开发者团队的严格管理)
- 每 6 周发布一个迭代版本
- 2-3 年发布一个新的大版本Rust 2018 editionRust 2021 edtion
好处在于,可以满足不同的用户群体的需求:
- 对于活跃的Rust用户他们总是能很快获取到新的语言内容毕竟尝鲜是技术爱好者的共同特点:)
- 对于一般的用户edition大版本的发布会告诉他们Rust语言相比上次大版本发布有了重大的改进值得一看
- 对于Rust语言开发者可以让他们的工作成果更快的被世人所知不必锦衣夜行
好了相信大家听了这么多Rust的优点已经迫不及待想要开始学习旅程那么容我引用一句CS的经典台词OKlet's go.
- 对于活跃的 Rust 用户,他们总是能很快获取到新的语言内容,毕竟,尝鲜是技术爱好者的共同特点:)
- 对于一般的用户edition 大版本的发布会告诉他们Rust 语言相比上次大版本发布,有了重大的改进,值得一看
- 对于 Rust 语言开发者,可以让他们的工作成果更快的被世人所知,不必锦衣夜行
好了,相信大家听了这么多 Rust 的优点,已经迫不及待想要开始学习旅程,那么容我引用一句 CS 的经典台词OK, let's go.
## 总结
连续6年最受欢迎的语言当然不是浪得虚名。 无GC、**效率高**、**工程性强**、强安全性以及能同时得到工程派和学院派认可, 这些令Rust拥有了自己的特色和生存空间社区的友善生态的快速发展大公司的重仓跟进一切的一切都在说明Rust的未来。
当然,语言毕竟还是工具,我们不能神话它,但是可以给它一个机会,也许你最终能收获自己的真爱:)
连续 6 年最受欢迎的语言当然不是浪得虚名。 无 GC、效率高、工程性强、强安全性以及能同时得到工程派和学院派认可这些令 Rust 拥有了自己的特色和生存空间。社区的友善,生态的快速发展,大公司的重仓跟进,一切的一切都在说明 Rust 的未来。
当然,语言毕竟只是工具,我们不能神话它,但是可以给它一个机会,也许,你最终能收获自己的真爱。:)

Loading…
Cancel
Save