Merge branch 'sunface:main' into main

pull/1126/head
Rustln 2 years ago committed by GitHub
commit 61049a0c24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -95,7 +95,7 @@ serde = ["dep:serde", "rgb?/serde"]
这里定义了以下关系:
1. 开启 `serde` feature 将启用可选的 `serde` 依赖
2. 只有当 `rgp` 依赖在其它地方已经被启用后,此处才能启用 `rgb``serde` feature
2. 只有当 `rgb` 依赖在其它地方已经被启用后,此处才能启用 `rgb``serde` feature
## 增量编译重启开启
在 [1.59 更新说明中](https://course.rs/appendix/rust-versions/1.59.html),我们有提到因为某些问题,增量编译被默认关闭了,现在官方修复了其中一些,并且确认目前的状态不会再影响用户的使用,因此在 1.60 版本中,增量编译又重新默认开启了。

@ -111,6 +111,48 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
这种就是 Rust 的安全特性之一。在很多系统编程语言中,并不会检查数组越界问题,你会访问到无效的内存地址获取到一个风马牛不相及的值,最终导致在程序逻辑上出现大问题,而且这种问题会非常难以检查。
#### 数组元素为非基础类型
学习了上面的知识很多朋友肯定觉得已经学会了Rust的数组类型但现实会给我们一记重锤实际开发中还会碰到一种情况就是**数组元素是非基本类型**的,这时候大家一定会这样写。
```rust
let array = [String::from("rust is good!"); 8];
println!("{:#?}", array);
```
然后你会惊喜的得到编译错误。
```console
error[E0277]: the trait bound `String: std::marker::Copy` is not satisfied
--> src/main.rs:7:18
|
7 | let array = [String::from("rust is good!"); 8];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `String`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
```
有些还没有看过特征的小伙伴,有可能不太明白这个报错,不过这个目前可以不提,我们就拿之前所学的[所有权](https://course.rs/basic/ownership/ownership.html)知识就可以思考明白前面几个例子都是Rust的基本类型而**基本类型在Rust中赋值是以Copy的形式**,这时候你就懂了吧,`let array=[3;5]`底层就是不断的Copy出来的但很可惜复杂类型都没有深拷贝只能一个个创建。
接着就有小伙伴会这样写。
```rust
let array = [String::from("rust is good!"),String::from("rust is good!"),String::from("rust is good!")];
println!("{:#?}", array);
```
作为一个追求极致完美的Rust开发者怎么能容忍上面这么难看的代码存在
**正确的写法**,应该调用`std::array::from_fn`
```rust
let array: [String; 8] = core::array::from_fn(|i| String::from("rust is good!"));
println!("{:#?}", array);
```
## 数组切片
在之前的[章节](https://course.rs/basic/compound-type/string-slice.html#切片slice),我们有讲到 `切片` 这个概念,它允许你引用集合中的部分连续片段,而不是整个集合,对于数组也是,数组切片允许我们引用数组的一部分:

@ -392,11 +392,14 @@ println!("{:p}", v.as_ptr()) // => 0x600002324050
```rust
fn main() {
// {使用{转义,}使用} => Hello {}
println!("Hello {{}}");
// "{{" 转义为 '{' "}}" 转义为 '}' "\"" 转义为 '"'
// => Hello "{World}"
println!(" Hello \"{{World}}\" ");
// 下面代码会报错,因为占位符{}只有一个右括号},左括号被转义成字符串的内容
// println!("{{ Hello }");
// println!(" {{ Hello } ");
// 也不可使用 '\' 来转义 "{}"
// println!(" \{ Hello \} ")
}
```

@ -15,32 +15,32 @@
```rust
// Rust 程序入口函数,跟其它语言一样,都是 main该函数目前无返回值
fn main() {
// 使用let来声明变量进行绑定a是不可变的
// 此处没有指定a的类型编译器会默认根据a的值为a推断类型i32有符号32位整数
// 语句的末尾必须以分号结尾
let a = 10;
// 主动指定b的类型为i32
let b: i32 = 20;
// 这里有两点值得注意:
// 1. 可以在数值中带上类型:30i32表示数值是30类型是i32
// 2. c是可变的mut是mutable的缩写
let mut c = 30i32;
// 还能在数值和类型中间添加一个下划线,让可读性更好
let d = 30_i32;
// 跟其它语言一样,可以使用一个函数的返回值来作为另一个函数的参数
let e = add(add(a, b), add(c, d));
// println!是宏调用,看起来像是函数但是它返回的是宏定义的代码块
// 该函数将指定的格式化字符串输出到标准输出中(控制台)
// {}是占位符在具体执行过程中会把e的值代入进来
println!("( a + b ) + ( c + d ) = {}", e);
}
// 定义一个函数输入两个i32类型的32位有符号整数返回它们的和
fn add(i: i32, j: i32) -> i32 {
// 返回相加值这里可以省略return
i + j
}
// 使用let来声明变量进行绑定a是不可变的
// 此处没有指定a的类型编译器会默认根据a的值为a推断类型i32有符号32位整数
// 语句的末尾必须以分号结尾
let a = 10;
// 主动指定b的类型为i32
let b: i32 = 20;
// 这里有两点值得注意:
// 1. 可以在数值中带上类型:30i32表示数值是30类型是i32
// 2. c是可变的mut是mutable的缩写
let mut c = 30i32;
// 还能在数值和类型中间添加一个下划线,让可读性更好
let d = 30_i32;
// 跟其它语言一样,可以使用一个函数的返回值来作为另一个函数的参数
let e = add(add(a, b), add(c, d));
// println!是宏调用,看起来像是函数但是它返回的是宏定义的代码块
// 该函数将指定的格式化字符串输出到标准输出中(控制台)
// {}是占位符在具体执行过程中会把e的值代入进来
println!("( a + b ) + ( c + d ) = {}", e);
}
// 定义一个函数输入两个i32类型的32位有符号整数返回它们的和
fn add(i: i32, j: i32) -> i32 {
// 返回相加值这里可以省略return
i + j
}
```
> 注意

@ -64,7 +64,7 @@ match x {
### 通过序列 `..=` 匹配值的范围
在[数值类型](https://course.rs/basic/base-type/numbers.html#序列range)中我们有讲到一个序列语法,该语法不仅可以用循环中,还能用于匹配模式。
在[数值类型](https://course.rs/basic/base-type/numbers.html#序列range)中我们有讲到一个序列语法,该语法不仅可以用循环中,还能用于匹配模式。
`..=` 语法允许你匹配一个闭区间序列内的值。在如下代码中,当模式匹配任何在此序列内的值时,该分支会执行:

@ -74,7 +74,7 @@ fn main() {
#### self、&self 和 &mut self
接下的内容非常重要,请大家仔细看。在 `area` 的签名中,我们使用 `&self` 替代 `rectangle: &Rectangle``&self` 其实是 `self: &Self` 的简写(注意大小写)。在一个 `impl` 块内,`Self` 指代被实现方法的结构体类型,`self` 指代此类型的实例,换句话说,`self` 指代的是 `Rectangle` 结构体实例,这样的写法会让我们的代码简洁很多,而且非常便于理解:我们为哪个结构体实现方法,那么 `self` 就是指代哪个结构体的实例。
接下的内容非常重要,请大家仔细看。在 `area` 的签名中,我们使用 `&self` 替代 `rectangle: &Rectangle``&self` 其实是 `self: &Self` 的简写(注意大小写)。在一个 `impl` 块内,`Self` 指代被实现方法的结构体类型,`self` 指代此类型的实例,换句话说,`self` 指代的是 `Rectangle` 结构体实例,这样的写法会让我们的代码简洁很多,而且非常便于理解:我们为哪个结构体实现方法,那么 `self` 就是指代哪个结构体的实例。
需要注意的是,`self` 依然有所有权的概念:

@ -1,6 +1,6 @@
## 认识 Cargo
但凡经历过 C/C++ 或 Go 语言 1.10 版本之前的用户都知道,一个好的包管理工具有多么的重要!!我那个时候是如此的渴望类似 `nodejs``npm `包管理工具,但是却求而不得。
但凡经历过 C/C++ 或 Go 语言 1.10 版本之前的用户都知道,一个好的包管理工具有多么的重要!!我那个时候是如此的渴望类似 `nodejs``npm` 包管理工具,但是却求而不得。
包管理工具最重要的意义就是**任何用户拿到你的代码,都能运行起来**,而不会因为各种包版本依赖焦头烂额。
@ -119,7 +119,7 @@ $ cargo check
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
```
> Rust 虽然编译速度还行,但是还是不能 Go 语言相提并论,因为 Rust 需要做很多复杂的编译优化和语言特性解析,甚至连如何优化编译速度都成了一门学问: [优化编译速度](https://course.rs/profiling/compiler/speed-up.html)
> Rust 虽然编译速度还行,但是还是不能 Go 语言相提并论,因为 Rust 需要做很多复杂的编译优化和语言特性解析,甚至连如何优化编译速度都成了一门学问: [优化编译速度](https://course.rs/profiling/compiler/speed-up.html)
## Cargo.toml 和 Cargo.lock

Loading…
Cancel
Save