Skip to content

Commit f5021df

Browse files
author
chenyuchun
committed
feat & fix: new page start for rust, correct errors in ownership
1 parent a175aee commit f5021df

File tree

6 files changed

+301
-21
lines changed

6 files changed

+301
-21
lines changed

docs/languages/rust/generics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn divide(a: i32, b: i32) -> Result<i32, String>{
7070

7171
```rust
7272
fn main() {
73-
let a:Option<String> = Some("hello".to_string());
73+
let a:Option<String> = Some("hello".to_string());
7474
let b: Result<_,&str> = Err("world");
7575
let content = a.unwrap() + " " + b.expect("Empty content"); // If a is None or b is Err, this will panic.
7676
// a is None: thread 'main' panicked at ...:

docs/languages/rust/ownership.md

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ Rust 引入了**所有权(ownership)**的概念:
88
- 同一时刻每个值只有一个所有者。
99
- 当所有者失效,值也将被丢弃。
1010

11-
变量通过绑定的方式,获得对数据的所有权。如果一个绑定超出作用域,其绑定的数据将被自动释放
11+
## 变量绑定
12+
13+
变量通过绑定的方式,获得对数据的所有权。如果一个绑定超出作用域,其绑定的数据将被自动释放。
1214

1315
```rust
1416
let a = 1;
@@ -24,29 +26,47 @@ println!("{s1}, world!");
2426
// 此时将发生编译错误 error: borrow of moved value: `s1`
2527
```
2628

29+
!!! note "移动所有权"
30+
- 移动所有权是编译时的语义,不涉及程序运行时的数据移动,数据对应的内存区域并没有改变,只是更改了对应的变量名(类似C++的指针)。
31+
- 移动是默认行为(通过绑定或赋值),不需要像 C++ 那样用 std::move 来显式指定。
32+
33+
## 借用
34+
2735
但并非所有语境下的变量赋值都希望移交所有权,这个时候应该采用 Rust 中的**借用(borrow)**概念。
2836

37+
### 借用规则
38+
2939
```rust
3040
let v = vec![1, 2, 3];
3141
let v_ref = &v; // v_ref is a reference to v.
3242
```
3343

34-
!!! note "移动所有权"
35-
- 移动所有权是编译时的语义,不涉及程序运行时的数据移动,数据对应的内存区域并没有改变,只是更改了对应的变量名(类似C++的指针)。
36-
- 移动是默认行为(通过绑定或赋值),不需要像 C++ 那样用 std::move 来显式指定。
37-
- 原来的变量依然拥有对数据的所有权。
44+
!!! note "借用规则"
3845

46+
- 可以通过对变量取引用来借用变量中的数据的所有权,此时所有权本身并没有发生变化。
47+
- 当引用超过作用域,借用也随之结束。
48+
- 原来的变量依然拥有对数据的所有权。
3949

40-
当借用发生时,会对原来的变量增加限制:
41-
- 当一个变量有引用存在时,不能移交它所绑定的数据的所有权。
50+
```rust
51+
let v = vec![1, 2, 3];
52+
// v_ref is a reference to v.
53+
let v_ref = &v;
54+
// use v_ref to access the data in the vector v.
55+
assert_eq!(v[1], v_ref[1]);
56+
```
4257

43-
```rust
44-
let v = vec![1, 2, 3];
45-
let v_ref = &v;
46-
let v_new = v;
47-
// Moving ownership to v_new would invalidate v_ref.
48-
// error: cannot move out of `v` because it is borrowed
49-
```
58+
- 当借用发生时,会对原来的变量增加限制:
59+
- 当一个变量有引用存在时,不能移交它所绑定的数据的所有权。
60+
61+
```rust
62+
let v = vec![1, 2, 3];
63+
let v_ref = &v;
64+
let v_new = v;
65+
// Moving ownership to v_new would invalidate v_ref.
66+
// error: cannot move out of `v` because it is borrowed
67+
```
68+
69+
### 可变借用与不可变借用
5070

5171
Rust 类型系统中,变量被分为**可变****不可变**。在借用中,同理可分为**可变借用** `&mut`**不可变借用** `&`
5272
```rust
@@ -59,9 +79,11 @@ fn main() {
5979

6080
!!! note "借用规则"
6181
- 不能在某个对象不存在后继续保留对它的引用。一个对象可以
62-
- 同时存在**多个不可变**引用(&T)
82+
- 同时存在**多个不可变**引用(&T)
6383
- 或者**仅有一个可变引用**(&mut T)。
64-
- 以上两者不能同时存在
84+
- 以上两者不能同时存在。
85+
86+
### 函数参数中的借用
6587

6688
需要注意的是,**函数****参数传递**时,采用的是与变量赋值和借用相同的语法规则。如果不指定 `&``&mut`,变量会直接发生移动。
6789
```rust
@@ -99,7 +121,7 @@ fn main() {
99121
println!("x still works: {}, and so does y: {}", x, y);
100122
```
101123

102-
- 可以通过 `impl Copy for ...` 或 `#[derive(Copy)]` 宏为变量实现 Copy 特型
124+
- 可以通过 `impl Copy for ...` 或 `#[derive(Copy)]` 宏为变量实现 Copy 特型
103125
- 非基本类型在实现了 Copy 特型后,可以通过 `clone()` 等方法进行拷贝。
104126

105127
```rust

docs/languages/rust/reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## 可变与不可变引用
44

5-
Rust 用 `&` 运算符来创建变量的引用,用 `*` 运算符来解引用
5+
Rust 用 `&` 运算符来创建变量的引用,用 `*` 运算符来解引用
66

77
```rust
88
let a = 1; // a: i32

docs/languages/rust/start.md

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# Rust 快速入门
2+
3+
## Rust 环境安装
4+
5+
### 开发环境
6+
7+
你可以从选择以下任意一条路径,搭建 Rust 开发环境。
8+
9+
- Visual Studio + Rust Analyzer: 需要在本地安装好 `rustup`,Rust Analyzer插件能够在未编译的阶段提供代码报错与补全。
10+
11+
- JetBrains RustRover: JetBrains 提供现成的 Rust 编程环境,内置 Cargo,提供便捷的代码补全与编译运行。
12+
13+
- [Rust Playground](https://play.rust-lang.org/): 在线 Rust 编程环境。
14+
15+
### 编译工具链配置
16+
17+
#### 安装 rustup
18+
19+
在 Linux 或者 macOS 命令行环境下运行下述命令:
20+
21+
```bash
22+
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
23+
```
24+
25+
如果显示错误 `Commmand 'curl' not found`,运行下述命令:
26+
27+
```bash
28+
$ sudo apt update
29+
$ sudo apt install -y curl
30+
```
31+
安装完成后,重新运行上面的 rustup 安装命令。
32+
33+
如果网络正常,rustup 安装命令会提示下述信息:
34+
35+
```bash
36+
Current installation options:
37+
38+
39+
default host triple: aarch64-apple-darwin
40+
default toolchain: stable (default)
41+
profile: default
42+
modify PATH variable: yes
43+
44+
1) Proceed with installation (default)
45+
2) Customize installation
46+
3) Cancel installation
47+
>
48+
```
49+
50+
回车以后,它就会安装 Rust 所需要的编译器(rustc)、标准库(rust-std)等等。
51+
52+
!!! note "Windows 安装 rustup"
53+
54+
前往 https://forge.rust-lang.org/infra/other-installation-methods.html,在 **Other ways to install rustup** 中,找到:
55+
56+
- On Windows, download and run rustup-init.exe.
57+
58+
下载并运行 **rustup-init.exe**。
59+
60+
61+
#### 测试 rust 工具链
62+
63+
下载完成后,命令行会提示下述信息:
64+
65+
```bash
66+
Rust is installed now. Great!
67+
68+
To get started you may need to restart your current shell.
69+
This would reload your PATH environment variable to include
70+
Cargo's bin directory ($HOME/.cargo/bin).
71+
72+
To configure your current shell, run:
73+
source $HOME/.cargo/env
74+
```
75+
76+
此时 shell 配置已更新。重启终端,PATH 环境变量就会包括 rustup 安装路径。如果想要在当前终端使用 rust 编译器,你也可以直接运行:
77+
78+
```bash
79+
$ source $HOME/.cargo/env
80+
```
81+
82+
完成后,可以通过下述检查 `rustc` 是否成功安装:
83+
84+
```bash
85+
$ rustc --version
86+
```
87+
88+
如果正常输出`rustc`版本信息,说明安装成功了。
89+
90+
## Hello World!
91+
92+
### 直接使用 rustc 编译
93+
94+
在当前目录下,通过下述命令创建项目。
95+
96+
```bash
97+
$ touch hello.rs
98+
```
99+
100+
在 `hello.rs` 中,写入如下内容:
101+
102+
```rust
103+
fn main() {
104+
println!("Hello world!");
105+
}
106+
```
107+
108+
使用 `rustc` 编译,运行 `hello` 可执行程序并得到下述结果。
109+
110+
```bash
111+
$ rustc hello.rs
112+
$ ./hello
113+
Hello world!
114+
```
115+
116+
### 使用 Cargo 包管理器
117+
118+
你也可以通过 Cargo 包管理器来创建一个新项目。
119+
120+
```bash
121+
$ Cargo new hello
122+
```
123+
124+
此时 Cargo 会在你的当前目录下生成一个 `hello` 文件夹,进入文件夹,通过 `tree` 可以查看项目结构。
125+
126+
```bash
127+
$ cd hello
128+
$ tree
129+
.
130+
├── Cargo.toml
131+
└── src
132+
└── main.rs
133+
```
134+
135+
其中 `Cargo.toml` 为项目的配置文件,存放了项目的相关信息、依赖项等信息。
136+
137+
由 Cargo 生成的 `main.rs` 会默认生成上述 `Hello world!` 程序,直接编译运行即可。
138+
139+
```bash
140+
$ cargo run
141+
Compiling hello v0.1.0 (/.../hello)
142+
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.46s
143+
Running `target/debug/hello`
144+
Hello, world!
145+
```
146+
147+
## Rust 项目结构
148+
149+
Rust 采用**模块化**的项目结构,每个文件/文件夹都被视为一个模块,文件内部还可以定义多个/多重模块。
150+
151+
可以通过 `use` 来访问模块。
152+
153+
```rust
154+
// Consume that your src directory has main.rs and calendar.rs
155+
mod calendar;
156+
use calendar::get_day;
157+
158+
mod body {
159+
pub mod mouth {
160+
pub fn use_mouth() {}
161+
}
162+
}
163+
164+
mod language {
165+
pub mod Chinese{
166+
pub fn speak() {
167+
use crate::body;
168+
body::mouth::use_mouth();
169+
}
170+
}
171+
}
172+
173+
fn main() {
174+
get_day();
175+
language::Chinese::speak();
176+
}
177+
```
178+
179+
Rust 以**包(packages)**为项目单位,用户可以通过包构建、测试、分享**箱(crates)**(也成单元包,对应一个库或可执行文件)。用户也可以实现自己的箱,通过在 `Cargo.toml` 的 `[dependencies]` 中配置箱的对应路径,即可在程序中通过 `use` 使用自己的箱。
180+
181+
## Cargo 包管理器
182+
183+
Cargo 是 Rust 的一个非常便捷好用的**包管理器(*package manager*)**,许多 Rust 程序员都在使用 Cargo 来管理他们的 Rust 项目。Cargo 能够为你处理很多任务,比如**构建代码**、**下载代码所依赖的库**,以及**构建这些库**。(代码所需要的库通常被称为**依赖项**)
184+
185+
### 创建项目
186+
187+
```bash
188+
$ cargo new <your-project-name>
189+
```
190+
191+
### 编译项目
192+
193+
```bash
194+
$ cargo run # 编译并运行项目
195+
$ cargo build # 仅编译,不运行
196+
$ cargo check #不编译,检查错误
197+
```
198+
199+
如果希望发布项目,请使用 `cargo build --release` 对其进行项目优化。(此命令将在 target/release 而不是 target/debug 中创建可执行文件)
200+
201+
### 添加依赖
202+
203+
```bash
204+
$ cargo add <crate>
205+
```
206+
207+
通过该命令添加的依赖将会同步至 `Cargo.toml`中。
208+
209+
也可以直接在 `Cargo.toml` 中写入依赖,随后通过 `cargo check` 或 `cargo build` 直接构建。
210+
211+
### 自动格式化
212+
213+
```bash
214+
$ cargo fmt
215+
```
216+
217+
Cargo 提供了代码风格的自动统一,通过上述指令可快速实现缩进和换行的自动对齐。
218+
219+
### 运行测试
220+
221+
Cargo 可以通过 `#[test]` 标注测试函数,通过 `cargo test` 命令进行单元测试。
222+
223+
```rust
224+
fn multiple(x: i32, y: i32) -> i32 {
225+
x * y
226+
}
227+
228+
#[test]
229+
fn multiple_test() {
230+
assert_eq!(2, multiple(1, 2));
231+
}
232+
233+
fn main() {}
234+
```
235+
236+
运行 `cargo test` 并查看结果。
237+
238+
```bash
239+
$ cargo test
240+
Compiling Test v0.1.0 (/.../my_project)
241+
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.45s
242+
Running unittests src/main.rs (target/debug/deps/my_project-5ab9f918a19e3cb1)
243+
244+
running 1 test
245+
test multiple_test ... ok
246+
247+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
248+
```
249+
250+
可以通过 `cargo test -- <test-name> --test-threads=1` 来指定测试和同时运行的测试数。
251+
252+
!!! note "Tips"
253+
通过 `#[cfg(test)]` 可以实现测试代码仅在测试模式下编译。
254+
255+
更多 Cargo 的使用方法,请参考 Cargo 的[官方文档](https://doc.rust-lang.org/cargo/)
256+
257+
第三方包可以通过该链接查阅:https://crates.io

docs/languages/rust/trait.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,14 @@ fn animal_make_sound<T: CanMakeSound>(animal: T) -> String {
110110
}
111111
```
112112

113-
`Trait Bound` 也可以不仅包含一个 `trait`
113+
`Trait Bound` 也可以不仅包含一个 `trait`
114114

115115
```rust
116116
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32;
117117
// 此处的 Display、Clone 和 Debug 都是 rust 语言提供的 trait
118118
```
119119

120-
也可以采用 `where` 从句来简化过长的 `Trait Bound`
120+
也可以采用 `where` 从句来简化过长的 `Trait Bound`
121121

122122
```rust
123123
fn some_function<T, U>(t: T, u: U) -> i32

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ nav:
138138
- Rust 语言基础:
139139
- languages/rust/index.md
140140
- Rust 入门的一点经验: languages/rust/whyrust.md
141+
- Rust 快速入门: languages/rust/start.md
141142
- Rust 的所有权: languages/rust/ownership.md
142143
- Rust 的变量与类型: languages/rust/variable.md
143144
- Rust 的引用与借用: languages/rust/reference.md

0 commit comments

Comments
 (0)