Skip to content

Commit 2928554

Browse files
committed
feat: 🎸 更新 HRTBs 等内容
1 parent aca3517 commit 2928554

9 files changed

Lines changed: 137 additions & 67 deletions

File tree

docs/notes/[相关资料].md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242

4343
## 相关资源🔗
4444

45+
* 从零开始用 Rust 语言写一个基于 RISC-V 架构的 类 Unix 内核
46+
- 链接:https://rcore-os.cn/rCore-Tutorial-Book-v3/index.html
47+
4548
* Teach-rs 面向计算机科学专业学生的 Rust 编程语言
4649
- 链接:https://github.com/tweedegolf/teach-rs
4750

@@ -156,6 +159,9 @@
156159

157160
## 大牛博客
158161

162+
- pretzelhammer's Rust blog 🦀
163+
- 链接:https://github.com/pretzelhammer/rust-blog
164+
159165
- Manishearth-blog
160166
- 链接:https://manishearth.github.io/blog/categories/rust/
161167

docs/notes/awesome rust.md

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,56 @@
11
Rust 生态系统由许多库和工具组成,可用于构建各种应用程序。其中一些库包括:
22

3-
## Rust 前端框架
3+
## Rust frontend frameworks
4+
5+
- [Leptos](https://github.com/leptos-rs/leptos)
6+
7+
- [Yew](https://github.com/yewstack/yew)
8+
9+
- [Sycamore](https://github.com/sycamore-rs/sycamore)
10+
11+
- [Perseus](https://github.com/framesurge/perseus)
12+
13+
- [Sauron](https://github.com/ivanceras/sauron)
14+
15+
- [MoonZoon](https://github.com/MoonZoon/MoonZoon)
16+
17+
- [Percy](https://github.com/chinedufn/percy)
18+
19+
20+
## Rust Backend frameworks
21+
22+
- [Axum](https://github.com/tokio-rs/axum)
23+
24+
- [salvo](https://github.com/salvo-rs/salvo/)
25+
26+
- [Axum](https://github.com/tokio-rs/axum)
27+
28+
- [Rocket](https://rocket.rs/)
29+
30+
- [Tide](https://github.com/http-rs/tide)
31+
32+
- [Cot](https://github.com/CotApp/cot)
33+
34+
- [Gotham](https://gotham.rs/)
435

536
- [seed](https://github.com/seed-rs/seed)
637

7-
- [Actix](https://actix.rs/)
38+
- [Actix Web](https://actix.rs/)
39+
40+
- [Warp](https://github.com/seanmonstar/warp)
41+
42+
- [Loco](https://loco.rs/)
43+
44+
- [Thruster](https://github.com/thruster-rs/Thruster)
45+
46+
- [Dropshot](https://github.com/oxidecomputer/dropshot)
47+
48+
- [Rouille](https://github.com/tomaka/rouille)
49+
50+
## OpenAPI Documentation
51+
52+
- [utoipa](https://github.com/juhaku/utoipa)
53+
Simple, Fast, Code first and Compile time generated OpenAPI documentation for Rust
854

955
## Operating Systems
1056

@@ -28,6 +74,10 @@ Rust 生态系统由许多库和工具组成,可用于构建各种应用程序
2874

2975
## GUI
3076

77+
- [vizia](https://github.com/vizia/vizia)
78+
Vizia is a crate for building desktop GUI applications.
79+
https://book.vizia.dev/
80+
3181
- [gpui](https://www.gpui.rs)
3282
A fast, productive UI framework for Rust from the creators of Zed.
3383
https://github.com/topics/gpui
@@ -51,8 +101,8 @@ Rust 生态系统由许多库和工具组成,可用于构建各种应用程序
51101

52102
- [freya](https://github.com/marc2332/freya)
53103

54-
- [Vizia](https://github.com/vizia/vizia/)
55-
A declarative GUI library written in Rust
104+
- [egui](https://github.com/emilk/egui)
105+
An easy-to-use GUI library for Rust
56106

57107
## proxy
58108

docs/notes/详解内存布局.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,63 @@ fn example() {
173173
}
174174
```
175175

176+
## 数组与字符串内存布局
177+
178+
```rust
179+
fn main() {
180+
println!("\n========== 数组内存布局演示 ==========");
181+
let arr = [1, 2, 3, 4, 5]; // 栈上
182+
183+
println!("数组内存地址: {:p}", &arr);
184+
println!("第一个元素地址: {:p}", &arr[0]);
185+
println!("第二个元素地址: {:p}", &arr[1]);
186+
187+
println!("\n========== 字符串内存布局演示 ==========");
188+
let str_literal = "Hello"; // 存储在程序二进制中
189+
let string_heap = String::from("Hello"); // 存储在堆上
190+
191+
println!("字符串字面量地址: {:p}", str_literal);
192+
println!("String 对象地址: {:p}", &string_heap);
193+
println!("String 内容地址: {:p}", string_heap.as_ptr());
194+
195+
// 展示 String 的容量概念
196+
let mut dynamic_string = String::with_capacity(10);
197+
println!("初始容量: {}", dynamic_string.capacity());
198+
199+
dynamic_string.push_str("Hello");
200+
println!("添加内容后 - 长度: {}, 容量: {}",
201+
dynamic_string.len(), dynamic_string.capacity());
202+
203+
dynamic_string.push_str(" Rust Programming");
204+
println!("再次添加后 - 长度: {}, 容量: {}",
205+
dynamic_string.len(), dynamic_string.capacity());
206+
}
207+
```
208+
209+
```
210+
数组内存布局:
211+
┌─────────────────────────────────────────────────────────┐
212+
│ 栈内存 (Stack) │
213+
│ ┌───┬───┬───┬───┬───┐ │
214+
│ │ 1 │ 2 │ 3 │ 4 │ 5 │ [i32; 5] │
215+
│ └───┴───┴───┴───┴───┘ │
216+
│ 连续内存地址 │
217+
└─────────────────────────────────────────────────────────┘
218+
219+
字符串内存布局:
220+
┌─────────────────────────────────────────────────────────┐
221+
│ 栈内存 (Stack) │ 堆内存 (Heap) │
222+
│ ┌─────────────────┐ │ ┌─────────────────────────────┐│
223+
│ │ String 对象 │ │ │ 实际字符串数据 ││
224+
│ │ ┌─────────────┐ │ │ │ ┌─┬─┬─┬─┬─┬─┐ ││
225+
│ │ │ ptr ─┼─┼───┼──▶│ │H│e│l│l│o│\0│ ││
226+
│ │ │ len: 5 │ │ │ │ └─┴─┴─┴─┴─┴─┘ ││
227+
│ │ │ capacity: 8│ │ │ │ ││
228+
│ │ └─────────────┘ │ │ └─────────────────────────────┘│
229+
│ └─────────────────┘ │ │
230+
└─────────────────────────────────────────────────────────┘
231+
```
232+
176233
## 元组(Tuple)内存布局
177234

178235
让我们通过一个具体例子来理解元组的内存布局:

docs/第 22 章 闭包/22.5 闭包与生命周期.md

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
当使用闭包做参数或返回值的时候,生命周期会变得更加复杂。假设有下面这段代码:
44

5-
---
6-
75
```rust
86
fn calc_by<'a, F>(var: &'a i32, f: F) -> i32
97
where F: Fn(&'a i32) -> i32
@@ -18,25 +16,17 @@ fn main() {
1816
}
1917
```
2018

21-
---
22-
23-
这段代码可以编译通过。但是,假如我们把 calc\_by 的函数体稍微改一下,变成下面这样:
24-
25-
---
19+
这段代码可以编译通过。但是,假如我们把 `calc_by` 的函数体稍微改一下,变成下面这样:
2620

2721
```rust
2822
let local = *var;
2923
f(&local)
3024
```
3125

32-
---
33-
3426
就不能编译通过了。
3527

3628
但是,如果我们把所有的生命周期标记去掉,变成这样:
3729

38-
---
39-
4030
```rust
4131
fn calc_by<F>(var: &i32, f: F) -> i32
4232
where F: Fn(&i32) -> i32
@@ -52,29 +42,21 @@ fn main() {
5242
}
5343
```
5444

55-
---
45+
这时所有的借用生命周期由编译器自动补全,又可以编译通过了。这说明,我们之前对这个 `calc_by` 函数手写的生命周期标记有问题。那我们手动来补全这些标记,应该怎么做呢?
5646

57-
它就又可以编译通过了。这说明,我们前面对这个 calc\_by 函数手写的生命周期标记有问题。
58-
59-
对于上面这个例子,所有的借用生命周期都是由编译器自动补全的,假如我们手动来补全这些标记,应该怎么做呢?
60-
61-
在这里我们只能使用“高阶生命周期”的表示方法:
62-
63-
---
47+
在这里我们只能使用“高阶生命周期约束”,即**高阶特征约束**(Higher-Ranked Trait Bounds)(HRTBs) 的表示方法:
6448

6549
```rust
6650
fn calc_by<'a, F>(var: &'a i32, f: F) -> i32
67-
where F: for<'f> Fn(&'f i32) -> i32
51+
where for<'f> F: Fn(&'f i32) -> i32
6852
{
6953
let local = *var;
7054
f(&local)
7155
}
7256
```
7357

74-
---
75-
76-
注意 F 的约束条件,这样写表示的意思是,Fn 的输入参数可作用于任意的生命周期'f,这个生命周期和另外一个参数 var 的生命周期没有半点关系。
58+
注意 `F` 的约束条件,其中 `for<'f>` 是高阶约束的标志,声明了一个**通用生命周期 `'f`**。这样写表示的意思是,Fn 的输入参数摆脱外部参数生命周期的限制,适配任意合法的生命周期`'f`。这个生命周期和另外一个参数 `var` 的生命周期没有半点关系。
7759

78-
这才是这段代码正确的生命周期标记方式。如果我们不手动标记出来,编译器为我们自动推导的生命周期关系就是这样的高阶生命周期
60+
这才是这段代码正确的生命周期标记方式。如果我们不手动标记出来,编译器会巧妙地创建了一些隐式的高阶生命周期参数边界(HRTBs)
7961

80-
谈到“高阶”这两个字,很多朋友会想到高阶类型(higher kinded types)。这里的高阶生命周期确实跟高阶类型有很多相似之处,Rust 也确实在思考如何引入高阶类型这个问题,但还没有做出最终决定。到目前为止,for<'a>Fn(&'a Arg)->&'a Ret 这样的语法,只能用于生命周期参数,不能用于任意泛型类型。
62+
谈到“高阶”这两个字,很多朋友会想到高阶类型(Higher-Kinded Types)。这里的高阶生命周期确实跟高阶类型有很多相似之处,Rust 也确实在思考如何引入高阶类型这个问题。到目前为止,`for<'a> Fn(&'a Arg) -> &'a Ret` 这样的语法,只能用于生命周期参数,不能用于任意泛型类型。

docs/第 25 章 协程/25.5 异步.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ async 和 await 关键字是目前许多语言都采用的主流方案,使用
88

99
## 25.5.1 核心构件 `Future`
1010

11-
Future 是一个 Trait,Future 可以组合,一个 Future 可以由其他的一个或者多个 Future 包装而成。跟我们已经见过的迭代器 Iterator 很像。比如,我们可以实现一个新的 Future,它的结果是多个 Future 按顺序执行得到的。或者,实现一个 Future,它的结果是两个子 Future 中先返回的那个。Future 组合的方式可以非常灵活。
11+
Future 是一个 Trait,Future 可以组合,一个 Future 可以由其他的一个或者多个 Future 包装而成。跟我们已经见过的迭代器 Iterator 很像。
1212

1313
其简化定义如下:
1414

docs/第 25 章 协程/25.6 Coroutine 与 Future.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
> **关键洞察**:在 `std` 层面,`Future``Coroutine` 是两个正交(Orthogonal)的概念。`Future`**面向生态的协议**,而 `Coroutine`**面向编译器的原语**。它们被设计为可以独立存在,这增加了语言的灵活性和模块化程度。
2222
23-
---
24-
2523
### **第二层:`async/await` —— 胶水和魔法的来源(在编译器中)**
2624

2725
现在,我们有了两种积木,但它们如何协同工作来构建出我们想要的城堡(即 `async` 函数)呢?这就是 `async/await` 语法和编译器发挥作用的地方。

docs/第 4 章 函数/4.1 简介.md

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,28 @@
11
# 4.1 简介
22

3-
Rust 的函数使用关键字`fn`开头。函数可以有一系列的输入参数,还有一个返回类型。函数体包含一系列的语句(或者表达式)。函数返回可以使用 return 语句,也可以使用表达式。Rust 编写的可执行程序的入口就是`fn main()`函数。以下是一个函数的示例:
4-
5-
---
3+
Rust 的函数使用关键字`fn`开头。函数可以有一系列的输入参数,还有一个返回类型。函数体包含一系列的语句(或者表达式)。函数返回可以使用 `return` 语句,也可以使用表达式。
4+
Rust 编写的可执行程序的入口就是 `fn main()` 函数。以下是一个函数的示例:
65

76
```rust
8-
fn add1(t : (i32,i32)) -> i32 {
7+
fn add1(t: (i32,i32)) -> i32 {
98
t.0 + t.1
109
}
1110
```
1211

13-
---
14-
15-
这个函数有一个输入参数,其类型是 tuple(i32,i32)。它有一个返回值,返回类型是 i32。函数的参数列表与 let 语句一样,也是一个“模式解构”。模式解构的详细解释请参考第 7 章。上述函数也可以写成下面这样:
16-
17-
---
12+
这个函数有一个输入参数,其类型是 tuple `(i32,i32)`。它有一个返回值,返回类型是 `i32`。函数的参数列表与 let 语句一样,也是一个“模式解构”。模式解构的详细解释请参考第 7 章。上述函数也可以写成下面这样:
1813

1914
```rust
2015
fn add2((x,y) : (i32,i32)) -> i32 {
2116
x + y
2217
}
2318
```
2419

25-
---
26-
2720
函数体内部是一个表达式,这个表达式的值就是函数的返回值。也可以写`return x + y;`这样的语句作为返回值,效果是一样的。
2821

29-
函数也可以不写返回类型,在这种情况下,编译器会认为返回类型是`unit()`。此处和表达式的规定是一致的。
22+
函数也可以不写返回类型,在这种情况下,编译器会认为返回类型是 unit 类型 `()`。此处和表达式的规定是一致的。
3023

3124
函数可以当成头等公民(first class value)被复制到一个值中,这个值可以像函数一样被调用。示例如下:
3225

33-
---
34-
3526
```rust
3627
fn main() {
3728
let p = (1, 3);
@@ -75,11 +66,7 @@ error[E0308]: mismatched types
7566
found type `fn((i32, i32)) -> i32 {add2}`
7667
```
7768

78-
---
79-
80-
虽然`add1``add2`有同样的参数类型和同样的返回值类型,但它们是不同类型,所以这里报错了。修复方案是让 func 的类型为通用的 fn 类型即可:
81-
82-
---
69+
虽然 `add1``add2` 有同样的参数类型和同样的返回值类型,但它们是不同类型,所以这里报错了。修复方案是让 func 的类型为通用的 fn 类型即可:
8370

8471
```rust
8572
// 写法一,用 as 类型转换
@@ -88,12 +75,8 @@ let mut func = add1 as fn((i32,i32))->i32;
8875
let mut func : fn((i32,i32))->i32 = add1;
8976
```
9077

91-
---
92-
9378
以上两种写法都能修复上面的编译错误。但是,我们不能在参数、返回值类型不同的情况下作类型转换,比如:
9479

95-
---
96-
9780
```rust
9881
fn add3(x: i32, y: i32) -> i32 {
9982
x + y
@@ -106,14 +89,10 @@ fn main() {
10689
}
10790
```
10891

109-
---
110-
111-
这里再加了一个`add3`函数,它接受两个 i32 参数,这就跟`add1``add2`有了本质区别。`add1``add2`是一个参数,类型是 tuple 包含两个 i32 成员,而`add3`是两个 i32 参数。三者完全不一样,它们之间是无法进行类型转换的。
92+
这里再加了一个 `add3` 函数,它接受两个 i32 参数,这就跟 `add1``add2` 有了本质区别。`add1``add2` 是一个参数,类型是 tuple 包含两个 i32 成员,而 `add3` 是两个 i32 参数。三者完全不一样,它们之间是无法进行类型转换的。
11293

11394
另外需要提示的就是,Rust 的函数体内也允许定义其他 item,包括静态变量、常量、函数、trait、类型、模块等。比如:
11495

115-
---
116-
11796
```rust
11897
fn test_inner() {
11998
static INNER_STATIC: i64 = 42;
@@ -138,6 +117,4 @@ fn test_inner() {
138117
}
139118
```
140119

141-
---
142-
143120
当你需要一些 item 仅在此函数内有用的时候,可以把它们直接定义到函数体内,以避免污染外部的命名空间。

docs/第 6 章 数组和字符串/6.2 字符串.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main () {
1717

1818
创建字符串类型的方法有多种。==`String`类型是在堆上分配的,而`&str`类型通常是指向现有字符串的指针,该字符串可以是堆栈、堆、已编译对象代码的数据段中的字符串==。
1919

20-
## 6.2.1 &str
20+
## 6.2.1 `&str`
2121

2222
`str`是 Rust 的内置类型,开发中基本不会使用。通常使用`&str`类型,是对`str`的借用,其实际上指向了一段 UTF-8 编码的字节数组的指针,因此可以看作是`[u8]`类型的切片形式`&[u8]`,是一种固定大小的字符串类型。
2323

@@ -115,9 +115,9 @@ fn main() {
115115
}
116116
```
117117

118-
## 6.2.2 String
119-
String 类型是 Rust 标准库提供的一种可增长的字符串类型,
120-
其实际上是一个包含了指向堆上分配的 UTF-8 编码字节数组的指针、字节数组的长度和容量等信息的结构体,并且提供了很多字符串相关的函数。
118+
## 6.2.2 `String`
119+
120+
`String` 类型是 Rust 标准库提供的一种可增长的字符串类型,其实际上是一个包含了指向堆上分配的 UTF-8 编码字节数组的指针、字节数组的长度和容量等信息的结构体,并且提供了很多字符串相关的函数。
121121

122122
==它跟`&str`类型的主要区别是,它有管理内存空间的权力==。
123123
关于“所有权”和“借用”的关系,在本书第二部分会详细讲解。

docs/附录 词汇表.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
| Fat Pointer | 胖指针,即还携带额外信息的指针 |
2727
| Feature Gate | 功能开关 |
2828
| FFI | Foreign Function Interface |
29-
| Fn/FnMut/FnOnce | 闭包相关的系列 trait |
29+
| Fn/FnMut/FnOnce | 闭包相关的系列 trait |
3030
| Generic | 泛型 |
3131
| Higher Rank Lifetime | 高阶生命周期 |
3232
| Higher Rank Trait Bounds | 高阶 trait 约束 |

0 commit comments

Comments
 (0)