From 367edd635050e80d549a49ffebedd6bff1195710 Mon Sep 17 00:00:00 2001 From: gfzum Date: Fri, 24 Feb 2023 16:56:05 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E5=9C=B0=E6=96=B9=E7=9A=84=E6=97=A0=E5=BA=8F=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E4=B9=A0=E6=83=AF=EF=BC=8C=E5=88=A0=E5=8E=BB?= =?UTF-8?q?=E4=BA=86=E6=AF=8F=E8=A1=8C=E7=9A=84=E5=8F=A5=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/ownership/ownership.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/basic/ownership/ownership.md b/src/basic/ownership/ownership.md index 1c26bf4e..9ff99515 100644 --- a/src/basic/ownership/ownership.md +++ b/src/basic/ownership/ownership.md @@ -260,11 +260,11 @@ Rust 有一个叫做 `Copy` 的特征,可以用在类似整型这样在栈中 那么什么类型是可 `Copy` 的呢?可以查看给定类型的文档来确认,不过作为一个通用的规则: **任何基本类型的组合可以 `Copy` ,不需要分配内存或某种形式资源的类型是可以 `Copy` 的**。如下是一些 `Copy` 的类型: -- 所有整数类型,比如 `u32`。 -- 布尔类型,`bool`,它的值是 `true` 和 `false`。 -- 所有浮点数类型,比如 `f64`。 -- 字符类型,`char`。 -- 元组,当且仅当其包含的类型也都是 `Copy` 的时候。比如,`(i32, i32)` 是 `Copy` 的,但 `(i32, String)` 就不是。 +- 所有整数类型,比如 `u32` +- 布尔类型,`bool`,它的值是 `true` 和 `false` +- 所有浮点数类型,比如 `f64` +- 字符类型,`char` +- 元组,当且仅当其包含的类型也都是 `Copy` 的时候。比如,`(i32, i32)` 是 `Copy` 的,但 `(i32, String)` 就不是 - 不可变引用 `&T` ,例如[转移所有权](#转移所有权)中的最后一个例子,**但是注意: 可变引用 `&mut T` 是不可以 Copy的** ## 函数传值与返回 From 03fdf2605b1a14e6a7127d6a3e89d48bdf8ce574 Mon Sep 17 00:00:00 2001 From: gfzum Date: Fri, 24 Feb 2023 18:38:17 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=B02.4=E4=B8=BA=E6=AD=A2=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E6=A0=87=E7=82=B9=E8=A1=A5=E9=BD=90=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/base-type/char-bool.md | 2 +- src/basic/base-type/numbers.md | 2 +- src/basic/compound-type/enum.md | 2 +- src/basic/compound-type/string-slice.md | 4 ++-- src/basic/compound-type/struct.md | 2 +- src/basic/intro.md | 3 +-- src/basic/ownership/borrowing.md | 2 +- src/first-try/cargo.md | 4 ++-- src/first-try/editor.md | 1 - src/first-try/hello-world.md | 1 - src/first-try/installation.md | 2 +- src/first-try/intro.md | 1 - src/first-try/slowly-downloading.md | 2 +- 13 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/basic/base-type/char-bool.md b/src/basic/base-type/char-bool.md index 4f6fde33..05c3625b 100644 --- a/src/basic/base-type/char-bool.md +++ b/src/basic/base-type/char-bool.md @@ -37,7 +37,7 @@ $ cargo run 字符'中'占用了4字节的内存大小 ``` -> 注意,我们还没开始讲字符串,但是这里提前说一下,和一些语言不同,Rust 的字符只能用 `''` 来表示, `""` 是留给字符串的 +> 注意,我们还没开始讲字符串,但是这里提前说一下,和一些语言不同,Rust 的字符只能用 `''` 来表示, `""` 是留给字符串的。 ## 布尔(bool) diff --git a/src/basic/base-type/numbers.md b/src/basic/base-type/numbers.md index c89952c9..420938ef 100644 --- a/src/basic/base-type/numbers.md +++ b/src/basic/base-type/numbers.md @@ -7,7 +7,7 @@ Rust 使用一个相对传统的语法来创建整数(`1`,`2`,...)和浮点数(`1.0`,`1.1`,...)。整数、浮点数的运算和你在其它语言上见过的一致,都是通过常见的运算符来完成。 -> 不仅仅是数值类型,Rust 也允许在复杂类型上定义运算符,例如在自定义类型上定义 `+` 运算符,这种行为被称为运算符重载,Rust 具体支持的可重载运算符见[附录 B](https://course.rs/appendix/operators.html#运算符) +> 不仅仅是数值类型,Rust 也允许在复杂类型上定义运算符,例如在自定义类型上定义 `+` 运算符,这种行为被称为运算符重载,Rust 具体支持的可重载运算符见[附录 B](https://course.rs/appendix/operators.html#运算符)。 ## 整数类型 diff --git a/src/basic/compound-type/enum.md b/src/basic/compound-type/enum.md index 71fb54cf..31fe139b 100644 --- a/src/basic/compound-type/enum.md +++ b/src/basic/compound-type/enum.md @@ -208,7 +208,7 @@ enum Websocket { 在其它编程语言中,往往都有一个 `null` 关键字,该关键字用于表明一个变量当前的值为空(不是零值,例如整型的零值是 0),也就是不存在值。当你对这些 `null` 进行操作时,例如调用一个方法,就会直接抛出**null 异常**,导致程序的崩溃,因此我们在编程时需要格外的小心去处理这些 `null` 空值。 -> Tony Hoare, `null` 的发明者,曾经说过一段非常有名的话 +> Tony Hoare, `null` 的发明者,曾经说过一段非常有名的话: > > 我称之为我十亿美元的错误。当时,我在使用一个面向对象语言设计第一个综合性的面向引用的类型系统。我的目标是通过编译器的自动检查来保证所有引用的使用都应该是绝对安全的。不过在设计过程中,我未能抵抗住诱惑,引入了空引用的概念,因为它非常容易实现。就是因为这个决策,引发了无数错误、漏洞和系统崩溃,在之后的四十多年中造成了数十亿美元的苦痛和伤害。 diff --git a/src/basic/compound-type/string-slice.md b/src/basic/compound-type/string-slice.md index e4fd7382..6b950aea 100644 --- a/src/basic/compound-type/string-slice.md +++ b/src/basic/compound-type/string-slice.md @@ -95,7 +95,7 @@ let slice = &s[..]; > ``` > > 因为我们只取 `s` 字符串的前两个字节,但是本例中每个汉字占用三个字节,因此没有落在边界处,也就是连 `中` 字都取不完整,此时程序会直接崩溃退出,如果改成 `&s[0..3]`,则可以正常通过编译。 -> 因此,当你需要对字符串做切片索引操作时,需要格外小心这一点, 关于该如何操作 UTF-8 字符串,参见[这里](#操作-utf-8-字符串) +> 因此,当你需要对字符串做切片索引操作时,需要格外小心这一点, 关于该如何操作 UTF-8 字符串,参见[这里](#操作-utf-8-字符串)。 字符串切片的类型标识是 `&str`,因此我们可以这样声明一个函数,输入 `String` 类型,返回它的切片: `fn first_word(s: &String) -> &str `。 @@ -706,7 +706,7 @@ for b in "中国人".bytes() { 与其它系统编程语言的 `free` 函数相同,Rust 也提供了一个释放内存的函数: `drop`,但是不同的是,其它语言要手动调用 `free` 来释放每一个变量占用的内存,而 Rust 则在变量离开作用域时,自动调用 `drop` 函数: 上面代码中,Rust 在结尾的 `}` 处自动调用 `drop`。 -> 其实,在 C++ 中,也有这种概念: _Resource Acquisition Is Initialization (RAII)_。如果你使用过 RAII 模式的话应该对 Rust 的 `drop` 函数并不陌生 +> 其实,在 C++ 中,也有这种概念: _Resource Acquisition Is Initialization (RAII)_。如果你使用过 RAII 模式的话应该对 Rust 的 `drop` 函数并不陌生。 这个模式对编写 Rust 代码的方式有着深远的影响,在后面章节我们会进行更深入的介绍。 diff --git a/src/basic/compound-type/struct.md b/src/basic/compound-type/struct.md index e171b36c..e6cc3329 100644 --- a/src/basic/compound-type/struct.md +++ b/src/basic/compound-type/struct.md @@ -389,7 +389,7 @@ rect1 is Rectangle { 还有一个简单的输出 debug 信息的方法,那就是使用 [`dbg!` 宏](https://doc.rust-lang.org/std/macro.dbg.html),它会拿走表达式的所有权,然后打印出相应的文件名、行号等 debug 信息,当然还有我们需要的表达式的求值结果。**除此之外,它最终还会把表达式值的所有权返回!** -> `dbg!` 输出到标准错误输出 `stderr`,而 `println!` 输出到标准输出 `stdout` +> `dbg!` 输出到标准错误输出 `stderr`,而 `println!` 输出到标准输出 `stdout`。 下面的例子中清晰的展示了 `dbg!` 如何在打印出信息的同时,还把表达式的值赋给了 `width`: diff --git a/src/basic/intro.md b/src/basic/intro.md index 87123141..c1d9d503 100644 --- a/src/basic/intro.md +++ b/src/basic/intro.md @@ -44,10 +44,9 @@ fn add(i: i32, j: i32) -> i32 { ``` > 注意 -> 在上面的 `add` 函数中,不要为 `i+j` 添加 `;`,这会改变语法导致函数返回 `()` 而不是 `i32`,具体参见[语句和表达式](https://course.rs/basic/base-type/statement-expression.html) +> 在上面的 `add` 函数中,不要为 `i+j` 添加 `;`,这会改变语法导致函数返回 `()` 而不是 `i32`,具体参见[语句和表达式](https://course.rs/basic/base-type/statement-expression.html)。 有几点可以留意下: - 字符串使用双引号 `""` 而不是单引号 `''`,Rust 中单引号是留给单个字符类型(`char`)使用的 - Rust 使用 `{}` 来作为格式化输出占位符,其它语言可能使用的是 `%s`,`%d`,`%p` 等,由于 `println!` 会自动推导出具体的类型,因此无需手动指定 - diff --git a/src/basic/ownership/borrowing.md b/src/basic/ownership/borrowing.md index 77de45fa..561acea1 100644 --- a/src/basic/ownership/borrowing.md +++ b/src/basic/ownership/borrowing.md @@ -289,7 +289,7 @@ fn dangle() -> &String { // dangle 返回一个字符串的引用 // 危险! ``` -因为 `s` 是在 `dangle` 函数内创建的,当 `dangle` 的代码执行完毕后,`s` 将被释放, 但是此时我们又尝试去返回它的引用。这意味着这个引用会指向一个无效的 `String`,这可不对! +因为 `s` 是在 `dangle` 函数内创建的,当 `dangle` 的代码执行完毕后,`s` 将被释放,但是此时我们又尝试去返回它的引用。这意味着这个引用会指向一个无效的 `String`,这可不对! 其中一个很好的解决方法是直接返回 `String`: diff --git a/src/first-try/cargo.md b/src/first-try/cargo.md index ac10e42f..b75b0df4 100644 --- a/src/first-try/cargo.md +++ b/src/first-try/cargo.md @@ -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 @@ -129,7 +129,7 @@ $ cargo check - `Cargo.lock` 文件是 `cargo` 工具根据同一项目的 `toml` 文件生成的**项目依赖详细清单**,因此我们一般不用修改它,只需要对着 `Cargo.toml` 文件撸就行了。 -> 什么情况下该把 `Cargo.lock` 上传到 git 仓库里?很简单,当你的项目是一个可运行的程序时,就上传 `Cargo.lock`,如果是一个依赖库项目,那么请把它添加到 `.gitignore` 中 +> 什么情况下该把 `Cargo.lock` 上传到 git 仓库里?很简单,当你的项目是一个可运行的程序时,就上传 `Cargo.lock`,如果是一个依赖库项目,那么请把它添加到 `.gitignore` 中。 现在用 VSCode 打开上面创建的"世界,你好"项目,然后进入根目录的 `Cargo.toml` 文件,可以看到该文件包含不少信息: diff --git a/src/first-try/editor.md b/src/first-try/editor.md index f3db6544..f73d8f99 100644 --- a/src/first-try/editor.md +++ b/src/first-try/editor.md @@ -46,4 +46,3 @@ 4. `CodeLLDB`, Debugger 程序 好了,至此,VSCode 的配置就已经全部结束,是不是很简单?下面让我们来用 `Cargo` 创建一个 Rust 项目,然后用 VSCode 打开。 - diff --git a/src/first-try/hello-world.md b/src/first-try/hello-world.md index f74031a4..ffe870c8 100644 --- a/src/first-try/hello-world.md +++ b/src/first-try/hello-world.md @@ -122,4 +122,3 @@ fn main() { 具体运行代码就不给了,留给大家作为一个小练习,建议亲自动手尝试下。 至此,Rust 安装入门就已经结束。相信看到这里,你已经发现了本书与其它书的区别,其中最大的区别就是:**这本书就像优秀的国外课本一样,不太枯燥。也希望这本不太枯燥的书,能伴你长行,犹如一杯奶茶,细细品之,唇齿留香。** - diff --git a/src/first-try/installation.md b/src/first-try/installation.md index 1a30e46c..88f1d6eb 100644 --- a/src/first-try/installation.md +++ b/src/first-try/installation.md @@ -5,7 +5,7 @@ > haha,开个玩笑。读者乃大大,怎么能弃之不顾。 > -> 注意:如果你不想用或者不能用 rustup,请参见 [Rust 其它安装方法](https://forge.rust-lang.org/infra/other-installation-methods.html#other-rust-installation-methods) +> 注意:如果你不想用或者不能用 rustup,请参见 [Rust 其它安装方法](https://forge.rust-lang.org/infra/other-installation-methods.html#other-rust-installation-methods)。 至于版本,现在 Rust 稳定版特性越来越全了,因此下载最新稳定版本即可。由于你用的 Rust 版本可能跟本书写作时不一样,一些编译错误和警告可能也会有所不同。 diff --git a/src/first-try/intro.md b/src/first-try/intro.md index 187db0bc..35d24c14 100644 --- a/src/first-try/intro.md +++ b/src/first-try/intro.md @@ -8,4 +8,3 @@ 2. 搭建 VSCode 所需的环境 3. 简单介绍 Cargo 4. 实现一个酷炫多国语言版本的“世界,你好”的程序,并且谈谈对 Rust 语言的初印象 - diff --git a/src/first-try/slowly-downloading.md b/src/first-try/slowly-downloading.md index d4430a9f..de52aac4 100644 --- a/src/first-try/slowly-downloading.md +++ b/src/first-try/slowly-downloading.md @@ -23,7 +23,7 @@ export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_pr 为了使用 `crates.io` 之外的注册服务,我们需要对 `$HOME/.cargo/config.toml` ($CARGO_HOME 下) 文件进行配置,添加新的服务提供商,有两种方式可以实现:增加新的镜像地址和覆盖默认的镜像地址。 -> 这里推荐使用[科大的注册服务](http://mirrors.ustc.edu.cn/help/crates.io-index.html)来提升下载速度,以下注册服务的链接都是科大的 +> 这里推荐使用[科大的注册服务](http://mirrors.ustc.edu.cn/help/crates.io-index.html)来提升下载速度,以下注册服务的链接都是科大的。 #### 增加新的镜像地址 From 106dfb6b1b2d17eb9a71ff438fdfe817e6253081 Mon Sep 17 00:00:00 2001 From: gfzum Date: Sun, 26 Feb 2023 17:33:09 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E7=9A=84=E5=9C=B0typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/compound-type/struct.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/compound-type/struct.md b/src/basic/compound-type/struct.md index e6cc3329..18c208b5 100644 --- a/src/basic/compound-type/struct.md +++ b/src/basic/compound-type/struct.md @@ -184,7 +184,7 @@ println!("{:?}", user1); 上面定义的 `File` 结构体在内存中的排列如下图所示: -从图中可以清晰的看出 `File` 结构体两个字段 `name` 和 `data` 分别拥有底层两个 `[u8]` 数组的所有权(`String` 类型的底层也是 `[u8]` 数组),通过 `ptr` 指针指向底层数组的内存地址,这里你可以把 `ptr` 指针理解为 Rust 中的引用类型。 +从图中可以清晰地看出 `File` 结构体两个字段 `name` 和 `data` 分别拥有底层两个 `[u8]` 数组的所有权(`String` 类型的底层也是 `[u8]` 数组),通过 `ptr` 指针指向底层数组的内存地址,这里你可以把 `ptr` 指针理解为 Rust 中的引用类型。 该图片也侧面印证了:**把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段**。