Skip to content

Commit c5cc061

Browse files
author
WaySLOG
committed
Merge pull request #354 from wayslog/master
reformat as double blank in line tail
2 parents bd39a40 + dac46df commit c5cc061

File tree

10 files changed

+72
-65
lines changed

10 files changed

+72
-65
lines changed

concurrency-parallel-thread/message-passing.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use std::thread;
1212

1313
fn main() {
1414
// 创建一个通道
15-
let (tx, rx): (mpsc::Sender<i32>, mpsc::Receiver<i32>) = mpsc::channel();
15+
let (tx, rx): (mpsc::Sender<i32>, mpsc::Receiver<i32>) =
16+
mpsc::channel();
1617

1718
// 创建线程用于发送消息
1819
thread::spawn(move || {
@@ -60,7 +61,8 @@ impl fmt::Display for Student {
6061

6162
fn main() {
6263
// 创建一个通道
63-
let (tx, rx): (mpsc::Sender<Rc<Student>>, mpsc::Receiver<Rc<Student>>) = mpsc::channel();
64+
let (tx, rx): (mpsc::Sender<Rc<Student>>, mpsc::Receiver<Rc<Student>>) =
65+
mpsc::channel();
6466

6567
// 创建线程用于发送消息
6668
thread::spawn(move || {
@@ -76,7 +78,8 @@ fn main() {
7678
```
7779
编译代码,奇迹没有出现,编译时错误,错误提示:
7880
```
79-
error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<Student>` [E0277]
81+
error: the trait `core::marker::Send` is not
82+
implemented for the type `alloc::rc::Rc<Student>` [E0277]
8083
note: `alloc::rc::Rc<Student>` cannot be sent between threads safely
8184
```
8285
看来并不是所有类型的消息都可以通过通道发送,消息类型必须实现`marker trait Send`。Rust之所以这样强制要求,主要是为了解决并发安全的问题,再一次强调,**安全**是Rust考虑的重中之重。如果一个类型是`Send`,则表明它可以在线程间安全的转移所有权(`ownership`),当所有权从一个线程转移到另一个线程后,同一时间就只会存在一个线程能访问它,这样就避免了数据竞争,从而做到线程安全。`ownership`的强大又一次显示出来了。通过这种做法,在编译时即可要求所有的代码必须满足这一约定,这种方式方法值得借鉴,`trait`也是非常强大。
@@ -143,7 +146,9 @@ receive 2
143146
在代码中,我们故意让`main`所在的主线程睡眠2秒,从而让发送者所在线程优先执行,通过结果可以发现,发送者发送消息时确实没有阻塞。还记得在前面提到过很多关于通道的问题吗?从这个例子里面还发现什么没?除了不阻塞之外,我们还能发现另外的三个特征:
144147

145148
1. 通道是可以同时支持多个发送者的,通过`clone`的方式来实现。
146-
这类似于`Rc`的共享机制,其实从`Channel`所在的库名`std::sync::mpsc`也可以知道这点,因为`mpsc`就是多生产者单消费者(Multiple Producers Single Consumer)的简写。
149+
这类似于`Rc`的共享机制。
150+
其实从`Channel`所在的库名`std::sync::mpsc`也可以知道这点。
151+
因为`mpsc`就是多生产者单消费者(Multiple Producers Single Consumer)的简写。
147152
可以有多个发送者,但只能有一个接收者,即支持的N:1模式。
148153

149154
2. 异步通道具备消息缓存的功能,因为1和2是在没有接收之前就发了的,在此之后还能接收到这两个消息。

data-structure/stack.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,18 @@ struct StackNode<T> {
4343
>现在我们重点来看看第四行:
4444
我们**从里到外**拆分来看看,首先是`Box<StackNode<T>`,这里的`Box`是 Rust 用来显式分配堆内存的类型:
4545
46-
> `pub struct Box<T> where T: ?Sized(_);`
46+
> `pub struct Box<T> where T: ?Sized(_);`
4747
[详细文档请参考Rust的标准库](http://doc.rust-lang.org/nightly/std/boxed/struct.Box.html)
4848

49-
> 在 Rust 里面用强大的类型系统做了统一的抽象。在这里相当于在堆空间里申请了一块内存保存`StackNode<T>`
49+
> 在 Rust 里面用强大的类型系统做了统一的抽象。在这里相当于在堆空间里申请了一块内存保存`StackNode<T>`
5050
51-
> **为什么要这么做了?如果不用Box封装会怎么样呢?**
51+
> **为什么要这么做了?如果不用Box封装会怎么样呢?**
5252
53-
> 如果不用 Box 封装,rustc 编译器会报错,在 Rust 里面,rustc 默认使用栈空间,但是这里的`StackNode`定义的时候使用了递归的数据结构,next 属性的类型是 `StackNode<T>`,而这个类型是无法确定大小的,所有这种无法确定大小的类型,都不能保存在栈空间。所以需要使用`Box`来封装。这样的话`next`的类型就是一个指向某一块堆空间的指针,而指针是可以确定大小的,因此能够保存在栈空间。
53+
> 如果不用 Box 封装,rustc 编译器会报错,在 Rust 里面,rustc 默认使用栈空间,但是这里的`StackNode`定义的时候使用了递归的数据结构,next 属性的类型是 `StackNode<T>`,而这个类型是无法确定大小的,所有这种无法确定大小的类型,都不能保存在栈空间。所以需要使用`Box`来封装。这样的话`next`的类型就是一个指向某一块堆空间的指针,而指针是可以确定大小的,因此能够保存在栈空间。
5454
55-
> **那么为什么还需要使用`Option`来封装呢?**
55+
> **那么为什么还需要使用`Option`来封装呢?**
5656
57-
> `Option`是 Rust 里面的一个抽象类型,定义如下:
57+
> `Option`是 Rust 里面的一个抽象类型,定义如下:
5858
>
5959
```rust
6060
pub enum Option<T> {
@@ -103,7 +103,7 @@ impl<T> Stack<T> {
103103
- `new( )`比较简单,Stack 初始化的时候为空,栈顶元素 `top` 就没有任何值,所以 `top``None`
104104

105105
- `push( )`的主要功能是往栈里面推入元素,把新的 StackNode 指向 Stack 里面旧的值,同时更新 Stack 栈顶指向新进来的值。
106-
> 这里有个需要注意的地方是第8行代码里面,`let next = self.top.take();`,使用了 Option 类型的 take 方法:
106+
> 这里有个需要注意的地方是第8行代码里面,`let next = self.top.take();`,使用了 Option 类型的 take 方法:
107107
`fn take(&mut self) -> Option<T>`
108108
它会把 Option 类型的值取走,并把它的元素改为 None
109109

flow/repetition.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ i = 4 and j = 9
7474
再比如:
7575

7676
```rust
77-
let lines = "Content of line one\nContent of line two\nContent of line three\nContent of line four".lines();
77+
let lines = "Content of line one
78+
Content of line two
79+
Content of line three
80+
Content of line four".lines();
7881
for (linenumber, line) in lines.enumerate() {
7982
println!("{}: {}", linenumber, line);
8083
}

generic/generic.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
泛型
22
===================
33

4-
----------
54
我们在编程中,通常有这样的需求,为多种类型的数据编写一个功能相同的函数,如两个数的加法,希望这个函数既支持i8、i16、 i32 ....float64等等,甚至自定义类型,在不支持泛型的编程语言中,我们通常要为每一种类型都编写一个函数,而且通常情况下函数名还必须不同,例如:
65
```rust
76
fn add_i8(a:i8, b:i8) -> i8 {
@@ -79,9 +78,9 @@ fn main() {
7978
}
8079
```
8180

82-
>**输出:**
83-
>101
84-
>200.33
81+
>**输出:**
82+
>101
83+
>200.33
8584
8685
```add<T: Add<T, Output=T>>(a:T, b:T) -> T```就是我们泛型函数,返回值也是泛型T,Add<>中的含义可以暂时忽略,大体意思就是只要参数类型实现了Add trait,就可以被传入到我们的add函数,因为我们的add函数中有相加+操作,所以要求传进来的参数类型必须是可相加的,也就是必须实现了Add trait(具体参考std::ops::Add)。
8786

@@ -120,10 +119,10 @@ fn main() {
120119
println!("{:?}", add(p1, p2));
121120
}
122121
```
123-
>**输出:**
124-
>101
125-
200.33
126-
Point { x: 3, y: 3 }
122+
>**输出:**
123+
>101
124+
200.33
125+
Point { x: 3, y: 3 }
127126

128127
上面的例子稍微更复杂些了,只是我们增加了自定义的类型,然后让add函数依然可以在上面工作。如果对trait不熟悉,请查阅trait相关章节。
129128

@@ -163,9 +162,9 @@ fn main() {
163162
}
164163
```
165164

166-
>**输出:**
167-
>Point { x: 3.2, y: 3.2 }
168-
Point { x: 3, y: 3 }
165+
>**输出:**
166+
>Point { x: 3.2, y: 3.2 }
167+
Point { x: 3, y: 3 }
169168

170169
上面的列子更复杂了些,我们不仅让自定义的Point类型支持了add操作,同时我们也为Point做了泛型化。
171170

match/pattern.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ x: 1
2626

2727
在以上代码中,match作用域里的`x`这个变量被覆盖成了`'c'`,而出了这个作用域之后,变量又恢复成了原来的值。这和变量绑定的行为是一致的。
2828

29-
## 更强大的结构
29+
## 更强大的解构
3030

3131
在上一节里,我们初步了解了模式匹配在解构`enum`时候的便利性,事实上,在Rust中模式可以被用来对任何复合类型进行解构——struct/tuple/enum。现在我们要进行一个复杂点的例子,对`struct`进行解构。
3232

ownership-system/ownership.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ c.rs:4 println!("{}", a);
8585
let 标识符A = 标识符B; // 把“A”绑定资源的所有权转移给“B”
8686
```
8787
Move前后的内存示意如下:
88-
> **Before move:**
89-
a <=> 内存(地址:**A**,内容:"xyz")
90-
**After move:**
91-
a
92-
b <=> 内存(地址:**A**,内容:"xyz")
88+
> **Before move:**
89+
a <=> 内存(地址:**A**,内容:"xyz")
90+
**After move:**
91+
a
92+
b <=> 内存(地址:**A**,内容:"xyz")
9393

9494
被move的变量不可以继续被使用。否则提示错误`error: use of moved value`
9595

@@ -106,11 +106,11 @@ b <=> 内存(地址:**A**,内容:"xyz")
106106
```
107107
编译确实可以通过,输出为`100`。这是为什么呢,是不是跟move小节里的结论相悖了?
108108
其实不然,这其实是根据变量类型是否实现`Copy`特性决定的。对于实现`Copy`特性的变量,在move时会拷贝资源到新内存区域,并把新内存区域的资源`binding``b`
109-
> **Before move:**
110-
a <=> 内存(地址:**A**,内容:100)
111-
**After move:**
112-
a <=> 内存(地址:**A**,内容:100)
113-
b <=> 内存(地址:**B**,内容:100)
109+
> **Before move:**
110+
a <=> 内存(地址:**A**,内容:100)
111+
**After move:**
112+
a <=> 内存(地址:**A**,内容:100)
113+
b <=> 内存(地址:**B**,内容:100)
114114

115115
move前后的`a``b`对应资源内存的地址不同。
116116

@@ -129,11 +129,11 @@ move前后的`a`和`b`对应资源内存的地址不同。
129129
这个时候可以编译通过,并且成功打印"xyz"。
130130

131131
clone后的效果等同如下:
132-
> **Before move:**
133-
a <=> 内存(地址:**A**,内容:"xyz")
134-
**After move:**
135-
a <=> 内存(地址:**A**,内容:"xyz")
136-
b <=> 内存(地址:**B**,内容:"xyz")
132+
> **Before move:**
133+
a <=> 内存(地址:**A**,内容:"xyz")
134+
**After move:**
135+
a <=> 内存(地址:**A**,内容:"xyz")
136+
b <=> 内存(地址:**B**,内容:"xyz")
137137
注意,然后a和b对应的资源值相同,但是内存地址并不一样。
138138

139139

quickstart/primitive-type.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ fn main() {
4242

4343
**例如:**
4444
固定大小类型:
45-
> 1u8 1i8
46-
> 1u16 1i16
47-
> 1u32 1i32
45+
> 1u8 1i8
46+
> 1u16 1i16
47+
> 1u32 1i32
4848
> 1u64 1i64
4949
5050
可变大小类型:

quickstart/rust-travel.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99
- 创建一个 Doing 目录和 helloworld.rs 文件
1010

11-
> ps: mkdir ~/Doing
12-
> ps: cd ~/Doing
13-
> ps: notepad helloworld.rs # 作者偏向于使用 sublime 作为编辑器
14-
> ps: subl helloworld.rs # 本章以后使用 subl 代替 notepad
11+
> ps: mkdir ~/Doing
12+
> ps: cd ~/Doing
13+
> ps: notepad helloworld.rs # 作者偏向于使用 sublime 作为编辑器
14+
> ps: subl helloworld.rs # 本章以后使用 subl 代替 notepad
1515
1616
注意这里用的后缀名是.rs,一般编程语言的代码文件都有惯用的后缀名,比如:
1717
C语言是.c,java是.java,python是.py等等,**请务必记住Rust语言的惯用后缀名是.rs**(虽然用别的后缀名也能通过rustc的编译)。
@@ -26,13 +26,13 @@ fn main() {
2626

2727
- 编译 helloworld.rs 文件
2828

29-
> ps: rustc helloworld.rs
30-
> ps: rustc helloworld.rs -O # 也可以选择优化编译
29+
> ps: rustc helloworld.rs
30+
> ps: rustc helloworld.rs -O # 也可以选择优化编译
3131
3232
- 运行程序
3333

34-
> ps: ./helloworld.exe # windows 平台下需要加 .exe 后缀
35-
> Hello World!
34+
> ps: ./helloworld.exe # windows 平台下需要加 .exe 后缀
35+
> Hello World!
3636
3737
没有`ps:`前缀的表示为控制台打印输出。
3838

@@ -53,20 +53,20 @@ fn main() {
5353
5454
- 查看目录结构
5555

56-
> ps: tree # win10 powershell 自带有 tree 查看文件目录结构的功能
57-
> └─hellorust
56+
> ps: tree # win10 powershell 自带有 tree 查看文件目录结构的功能
57+
> └─hellorust
5858
> ----└─src
5959
6060
这里显示的目录结构,在hellorust目录下有 src 文件夹和 Cargo.toml 文件,同时这个目录会初始化为 git 项目
6161

6262
- 查看Cargo.toml文件
6363

64-
> ps: cat Cargo.toml
65-
> [package]
66-
name = "hellorust"
67-
version = "0.1."
64+
> ps: cat Cargo.toml
65+
> [package]
66+
name = "hellorust"
67+
version = "0.1."
6868
authors = ["YourName <YourEmail>"]
69-
> [dependencies]
69+
> [dependencies]
7070
7171
- 编辑src目录下的main.rs文件
7272

@@ -90,9 +90,9 @@ fn main() {
9090

9191
- 编译和运行
9292

93-
> ps: cargo build
94-
> ps: cargo build --release # 这个属于优化编译
95-
> ps: ./target/debug/hellorust.exe
96-
> ps: ./target/release/hellorust.exe # 如果前面是优化编译,则这样运行
97-
> ps: cargo run # 编译和运行合在一起
98-
> ps: cargo run --release # 同上,区别是是优化编译的
93+
> ps: cargo build
94+
> ps: cargo build --release # 这个属于优化编译
95+
> ps: ./target/debug/hellorust.exe
96+
> ps: ./target/release/hellorust.exe # 如果前面是优化编译,则这样运行
97+
> ps: cargo run # 编译和运行合在一起
98+
> ps: cargo run --release # 同上,区别是是优化编译的

quickstart/trait.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,6 @@ impl Graph for SimpleGraph {
202202

203203
let graph = SimpleGraph;
204204
let object = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
205+
205206
```
207+

rcarc/rcarc.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,11 @@ use std::rc::Rc;
9696

9797
struct Owner {
9898
name: String
99-
// ...other fields
10099
}
101100

102101
struct Gadget {
103102
id: i32,
104103
owner: Rc<Owner>
105-
// ...other fields
106104
}
107105

108106
fn main() {

0 commit comments

Comments
 (0)