Skip to content

Commit 3cac817

Browse files
author
chenyuchun
committed
update rust content
1 parent 7bdb6c3 commit 3cac817

File tree

10 files changed

+388
-108
lines changed

10 files changed

+388
-108
lines changed

docs/languages/rust/control.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ for i in (1 .. 10) { // (a .. b) 创建了一个数字序列 Range,表示半
4444
sum += i;
4545
}
4646
// 实际上这里的求和可以通过迭代器用更优雅和快速的方法重写,此处仅仅作为演示。
47+
let word: &str = "World";
48+
for letter in word.chars() { // 将 &str 类型转化为迭代器
49+
println!("{}", letter);
50+
}
51+
// 迭代器的简单示例
4752
```
4853

4954
### `while` 循环

docs/languages/rust/function.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Rust 中通过 `fn` 关键字声明函数,在函数名后的括号内声明参
88
fn func_1() {
99
println!("Hello");
1010
} // 无参数,无返回值的函数
11+
// 无返回值的函数,会默认返回 单位元 ()
1112

1213
fn func_with_param(i: u32, j: u32) {
1314
println!("I love you {} times", i + j);
@@ -29,6 +30,12 @@ fn func_with_return_value_mod(i: i32, j: i32) -> i32 {
2930

3031
在 C/C++ 中,函数的声明的类型在前,没有额外关键字。读者可能需要一些时间来适应 Rust 的语法。
3132

33+
!!! caution "函数返回值"
34+
35+
无返回值的函数会默认返回 **单位元** `()`,并非真实语义下的“无返回值”。
36+
Rust 编译器具有严格的类型检查,如果函数指定了返回值类型,但没有给出返回值或 return 语句,编译器将给出 `mismatched types` 报错。
37+
类似的,如果没给定返回值类型,但返回了 **非单位元** 类型的值,编译器也会给出 `mismatched types` 报错。
38+
3239
## 函数调用
3340

3441
Rust 的函数调用语法与 C/C++ 没有太大区别。

docs/languages/rust/generics.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Rust 的泛型
2+
3+
Rust 中的泛型通过如下方式实现:
4+
5+
## 泛型函数
6+
```rust
7+
fn foo<T, U>(x: T, y: U) {
8+
}
9+
```
10+
11+
## 泛型枚举
12+
```rust
13+
enum Result<T, E> {
14+
Ok(T),
15+
Err(E),
16+
}
17+
```
18+
19+
## 泛型结构体
20+
```rust
21+
struct Point<T> {
22+
x: T,
23+
y: T,
24+
}
25+
26+
impl<T> Point<T> // 在 impl 代码段开头声明泛型
27+
where
28+
T: std::ops::Add<Output = T> + std::ops::Mul<Output = T> + Copy,
29+
{
30+
fn distance_from_origin(&self) -> T {
31+
self.x * self.x + self.y * self.y
32+
}
33+
}
34+
```
35+
36+
## Option 和 Result 类型
37+
Rust 提供了两个非常方便的枚举类型:`Option``Result`
38+
```rust
39+
enum Option<T> {
40+
None,
41+
Some(T),
42+
}
43+
44+
enum Result<T,E> {
45+
Ok(T),
46+
Err(E),
47+
}
48+
```
49+
合理地运用这两个枚举类型,可以便捷地传递参数、捕获错误。
50+
51+
```rust
52+
fn eat(food: Option<String>) {
53+
match food {
54+
Some(c) => println!("Nice {}! I'm full.",c),
55+
None => println!("Nothing to eat. I'm hungry!"),
56+
}
57+
}
58+
59+
fn divide(a: i32, b: i32) -> Result<i32, String>{
60+
if b == 0 {
61+
return Err(String::from("Division by zero"));
62+
}
63+
64+
Ok(a / b)
65+
}
66+
```
67+
68+
!!! note "Option 与 Result 的数据获取"
69+
Rust 为 `Option``Result` 类型提供了 `unwrap()``expect()` 等方法进行快速的数据获取,可以绕开冗余的模式匹配。但程序员需要自己确保 `Option` 对应的类型为 `Some(_)``Result``Ok(_)`),否则会导致程序`panic`退出。
70+
71+
```rust
72+
fn main() {
73+
let a:Option<String> = Some("hello".to_string());
74+
let b: Result<_,&str> = Err("world");
75+
let content = a.unwrap() + " " + b.expect("Empty content"); // If a is None or b is Err, this will panic.
76+
// a is None: thread 'main' panicked at ...:
77+
// called `Option::unwrap()` on a `None` value
78+
// b is Err:thread 'main' panicked at ...:
79+
// Empty content: "world"
80+
println!("{}",content);
81+
}
82+
```
83+

docs/languages/rust/index.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,25 @@
1616

1717
不同于 JavaScript 和 Python 等语言,Rust 语言上手相对较为困难。因此,编写本文档的目的更类似于在假定读者拥有一定 C++ 基础的情况下,向读者提供一些学习 Rust 的对照性帮助,而非一个 Rust 入门教程。如果希望获得一份 Rust 入门教程,请参阅下方资源链接中的 The Book。
1818

19-
本文档覆盖了 The Book 的 第3(常见编程概念)、5(结构体)、6(枚举和模式匹配)章的主要内容,介绍了最为基本的语法,且不怎么涉及新概念(如所有权、生命周期
19+
本文档覆盖了 The Book 的 第3(常见编程概念)、5(结构体)、6(枚举和模式匹配)章的主要内容,介绍了最为基本的语法。在文档的开头,将简要介绍 Rust 中的所有权。生命周期、不安全代码、自动测试等高级概念,可以参考下述资源链接自行学习
2020

2121
## 资源链接
2222

23+
### 官方参考资料
2324
- The Rust Programming Language(也被称为 The Book)。Rust 官方网站推荐的 Rust 语言入门书籍 https://doc.rust-lang.org/book/
2425
- The Book 的中文社区翻译版,更新很及时 https://kaisery.github.io/trpl-zh-cn/
2526

26-
- Rustlings。Rust 官方推荐的另一种入门方式,适合喜欢边学边做的同学 https://github.com/rust-lang/rustlings/
27+
- Rustlings。Rust 官方推荐的另一种入门方式,适合喜欢边学边做的同学 https://github.com/rust-lang/rustlings/
28+
29+
### 入门教程
30+
- Rust 官方文档中文教程。https://rustwiki.org
31+
32+
- RUNOOB.COM 的 Rust 教程:简明的入门教程,可作为第一份学习资料。https://www.runoob.com/rust/rust-tutorial.html
33+
34+
### 阅读材料
35+
- Effective Rust。Rust 进阶教程,比较详细地介绍了 Rust 中类型(Types)、特型(Trait)及 Rust 语言的设计理念和使用方法。 https://www.lurklurk.org/effective-rust/
36+
37+
### 课程材料
38+
- CIS 198: Rust Programming:宾夕法尼亚大学的 Rust 课程。https://cis198-2016s.github.io
39+
40+
- 清华大学程序设计训练(Rust)文档:https://lab.cs.tsinghua.edu.cn/rust/

docs/languages/rust/matching.md

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,23 @@ let coin = Coin {
2222
};
2323
```
2424

25-
Rust 的枚举量中可以保存数据成员,十分强大。
25+
枚举的每种变体 (variant) 可以:
26+
- 没有数据(单位元变体)
27+
- 有命名的数据域(结构体变体)
28+
- 有不命名的有序数据域(元组变体)
2629

2730
```rust
28-
enum Coin {
29-
Dime(u32),
30-
Half(u32),
31-
Yuan(u32)
32-
} // 在一个枚举类型中完成类型和面值的记录
33-
34-
let coin = Coin::Dime(10);
35-
36-
enum AnotherEnum {
37-
TypeA(i32),
38-
TypeB(u32, f64),
39-
TypeC(String),
40-
TypeD
41-
} // 枚举类型的数据成员可以互不相同
31+
enum Resultish {
32+
Ok,
33+
Warning { code: i32, message: String },
34+
Err(String)
35+
}
4236
```
4337

4438
!!! note "与 C++ 的对照"
4539

46-
C/C++ 的枚举类型底层是整数,不能拥有数据成员。这是 Rust 和 C/C++ 的一个很大的区别。枚举类型是 Rust 提供给我们的有力武器。
40+
C/C++ 的枚举类型底层是整数,不能拥有数据成员。这是 Rust 和 C/C++ 的一个很大的区别。
41+
枚举类型是 Rust 提供给我们的有力武器。善用枚举类,可以便捷地传递很多数据。
4742

4843
## 匹配
4944

docs/languages/rust/ownership.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Rust 中的所有权
2+
3+
为了兼顾内存使用的**安全****性能**,Rust 在设计之初就采用了与 C++ 完全不同的内存管理。
4+
5+
Rust 引入了**所有权(ownership)**的概念:
6+
- Rust 中的每个值都有所有者 (owner)。
7+
- 同一时刻每个值只有一个所有者。
8+
- 当所有者失效,值也将被丢弃。
9+
10+
变量通过绑定的方式,获得对数据的所有权。如果一个绑定超出作用域,其绑定的数据将被自动释放
11+
12+
```rust
13+
let a = 1;
14+
```
15+
16+
变量之间的**赋值**行为,将会直接导致绑定关系的变化,这一语义被称为**移动所有权**,亦即**掩盖 (shadowing)**
17+
18+
```rust
19+
let s1 = String::from("hello");
20+
let s2 = s1; // 字符串 "hello" 已经被 s2 绑定,s1 悬置。
21+
22+
println!("{s1}, world!");
23+
// 此时将发生编译错误 error: borrow of moved value: `s1`
24+
```
25+
26+
但并非所有语境下的变量赋值都希望移交所有权,这个时候应该采用 Rust 中的**借用(borrow)**概念。
27+
28+
```rust
29+
let v = vec![1, 2, 3];
30+
let v_ref = &v; // v_ref is a reference to v.
31+
```
32+
33+
!!! note "移动所有权"
34+
- 移动所有权是编译时的语义,不涉及程序运行时的数据移动,数据对应的内存区域并没有改变,只是更改了对应的变量名(类似C++的指针)。
35+
- 移动是默认行为(通过绑定或赋值),不需要像 C++ 那样用 std::move 来显式指定。
36+
- 原来的变量依然拥有对数据的所有权。
37+
38+
39+
当借用发生时,会对原来的变量增加限制:
40+
- 当一个变量有引用存在时,不能移交它所绑定的数据的所有权。
41+
42+
```rust
43+
let v = vec![1, 2, 3];
44+
let v_ref = &v;
45+
let v_new = v;
46+
// Moving ownership to v_new would invalidate v_ref.
47+
// error: cannot move out of `v` because it is borrowed
48+
```
49+
50+
Rust 类型系统中,变量被分为**可变****不可变**。在借用中,同理可分为**可变借用** `&mut`**不可变借用** `&`
51+
```rust
52+
fn main() {
53+
let mut vector: Vec<i32> = vec![];
54+
let vector_ref: &mut Vec<i32> = &mut vector;
55+
push(vector_ref, 4);
56+
}
57+
```
58+
59+
!!! note "借用规则"
60+
- 不能在某个对象不存在后继续保留对它的引用。一个对象可以
61+
- 同时存在**多个不可变**引用(&T)
62+
- 或者**仅有一个可变引用**(&mut T)。
63+
- 以上两者不能同时存在
64+
65+
需要注意的是,**函数****参数传递**时,采用的是与变量赋值和借用相同的语法规则。如果不指定 `&``&mut`,变量会直接发生移动。
66+
```rust
67+
fn hello_move(s: String) {
68+
println!("Message by moving: {}", S);
69+
}
70+
71+
fn hello_borrow(s: &String) {
72+
println!("Message by borrowing: {}", S);
73+
}
74+
75+
fn main() {
76+
let x: String = String::from("hello");
77+
let y: String = String::from("hello");
78+
79+
hello_move(x);
80+
hello_borrow(&y);
81+
82+
println!("x:{}",x); // error[E0382]: borrow of moved value: `x`
83+
println!("y:{}",y); // This runs normally.
84+
}
85+
86+
```
87+
88+
!!! note "变量的拷贝"
89+
如果想要直接获得一份变量的副本,可以使用 Rust 的 Copy 特型。
90+
91+
- 大多数基本类型是 Copy 类型(i32、f64、char、bool 等等)。
92+
- 基本类型发生赋值时,会发生拷贝而非移动。
93+
94+
95+
```rust
96+
let x: i32 = 12;
97+
let y = x; // `i32` is `Copy`, so it's not moved :D
98+
println!("x still works: {}, and so does y: {}", x, y);
99+
```
100+
101+
- 可以通过 `impl Copy for ...` 或 `#[derive(Copy)]` 宏为变量实现 Copy 特型
102+
- 非基本类型在实现了 Copy 特型后,可以通过 `clone()` 等方法进行拷贝。
103+
104+
```rust
105+
let x: String = String::from("hello");
106+
let y = x.clone(); // here copy an 'x' to y
107+
println!("x still works: {}, and so does y: {}", x, y);
108+
```
109+
所有权的思想贯穿了 Rust 编程的全过程,在后续的 **变量****函数****结构体** 等章节中,你还会多次遇到所有权的**转移****借用**问题。

0 commit comments

Comments
 (0)