From f62aca2a777d4636e7dc7e4b82d4aa854435dcaf Mon Sep 17 00:00:00 2001 From: 0xmingx Date: Tue, 11 Oct 2022 22:49:43 +0800 Subject: [PATCH 01/14] fix bug the `msg` type here is `Message`, don't need `unwrap()`, then wrapping `msg.content` in `Some`, return to fit the `filter_map`'s trait bound: Option --- src/async-rust/tokio/stream.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/async-rust/tokio/stream.md b/src/async-rust/tokio/stream.md index 58b1773a..c7b07753 100644 --- a/src/async-rust/tokio/stream.md +++ b/src/async-rust/tokio/stream.md @@ -184,7 +184,7 @@ got = b"6" let messages = subscriber .into_stream() .filter_map(|msg| match msg { - Ok(msg) if msg.content.len() == 1 => msg.unwrap().content, + Ok(msg) if msg.content.len() == 1 => Some(msg.content), _ => None, }) .take(3); From 9fa98b9dfbb4380e050e79783015722edbaa94a7 Mon Sep 17 00:00:00 2001 From: 0xmingx Date: Thu, 13 Oct 2022 23:47:44 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这里应该是 `let` 和 `if let` 做比较 --- src/basic/match-pattern/pattern-match.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/match-pattern/pattern-match.md b/src/basic/match-pattern/pattern-match.md index 5b8837e5..3e823445 100644 --- a/src/basic/match-pattern/pattern-match.md +++ b/src/basic/match-pattern/pattern-match.md @@ -145,7 +145,7 @@ fn main() { `&(3, 5)` 会匹配模式 `&(x, y)`,因此 `x` 得到了 `3`,`y` 得到了 `5`。 -#### if 和 if let +#### let 和 if let 对于以下代码,编译器会报错: From ce5fde09dc8450cb12340c8434b4348d7898ed03 Mon Sep 17 00:00:00 2001 From: James Chen <36363555+loryhndol@users.noreply.github.com> Date: Sat, 29 Oct 2022 16:43:44 +0800 Subject: [PATCH 03/14] Update trait.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文件操作是不是漏了 close() ? 修补第98行的加粗问题 --- src/basic/trait/trait.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/basic/trait/trait.md b/src/basic/trait/trait.md index 8681e55f..0f1e89ef 100644 --- a/src/basic/trait/trait.md +++ b/src/basic/trait/trait.md @@ -1,8 +1,8 @@ # 特征 Trait -如果我们想定义一个文件系统,那么把该系统跟底层存储解耦是很重要的。文件操作主要包含三个:`open` 、`write`、`read`,这些操作可以发生在硬盘,可以发生在内存,还可以发生在网络IO甚至(...我实在编不下去了,大家来帮帮我)。总之如果你要为每一种情况都单独实现一套代码,那这种实现将过于繁杂,而且也没那个必要。 +如果我们想定义一个文件系统,那么把该系统跟底层存储解耦是很重要的。文件操作主要包含四个:`open` 、`write`、`read`、`close`,这些操作可以发生在硬盘,可以发生在内存,还可以发生在网络IO甚至(...我实在编不下去了,大家来帮帮我)。总之如果你要为每一种情况都单独实现一套代码,那这种实现将过于繁杂,而且也没那个必要。 -要解决上述问题,需要把这些行为抽象出来,就要使用 Rust 中的特征 `trait` 概念。可能你是第一次听说这个名词,但是不要怕,如果学过其他语言,那么大概率你听说过接口,没错,特征很类似接口。 +要解决上述问题,需要把这些行为抽象出来,就要使用 Rust 中的特征 `trait` 概念。可能你是第一次听说这个名词,但是不要怕,如果学过其他语言,那么大概率你听说过接口,没错,特征跟接口很类似。 在之前的代码中,我们也多次见过特征的使用,例如 `#[derive(Debug)]`,它在我们定义的类型(`struct`)上自动派生 `Debug` 特征,接着可以使用 `println!("{:?}", x)` 打印这个类型;再例如: @@ -95,7 +95,7 @@ sunface发表了微博好像微博没Tweet好用 上面我们将 `Summary` 定义成了 `pub` 公开的。这样,如果他人想要使用我们的 `Summary` 特征,则可以引入到他们的包中,然后再进行实现。 -关于特征实现与定义的位置,有一条非常重要的原则:**如果你想要为类型 `A` 实现特征 `T`,那么 `A` 或者 `T` 至少有一个是在当前作用域中定义的!**例如我们可以为上面的 `Post` 类型实现标准库中的 `Display` 特征,这是因为 `Post` 类型定义在当前的作用域中。同时,我们也可以在当前包中为 `String` 类型实现 `Summary` 特征,因为 `Summary` 定义在当前作用域中。 +关于特征实现与定义的位置,有一条非常重要的原则:**如果你想要为类型** `A` **实现特征** `T`**,那么** `A` **或者** `T` **至少有一个是在当前作用域中定义的!** 例如我们可以为上面的 `Post` 类型实现标准库中的 `Display` 特征,这是因为 `Post` 类型定义在当前的作用域中。同时,我们也可以在当前包中为 `String` 类型实现 `Summary` 特征,因为 `Summary` 定义在当前作用域中。 但是你无法在当前作用域中,为 `String` 类型实现 `Display` 特征,因为它们俩都定义在标准库中,其定义所在的位置都不在当前作用域,跟你半毛钱关系都没有,看看就行了。 From 057b6f917416ee1141b3ed20337ffc4b79ec5d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=8F=AF?= Date: Mon, 7 Nov 2022 19:20:54 +0800 Subject: [PATCH 04/14] Update panic.md --- src/basic/result-error/panic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/result-error/panic.md b/src/basic/result-error/panic.md index 67a77416..c9904844 100644 --- a/src/basic/result-error/panic.md +++ b/src/basic/result-error/panic.md @@ -182,4 +182,4 @@ let home: IpAddr = "127.0.0.1".parse().unwrap(); ## 课后练习 -> [Rust By Practice](https://zh.practice.rs/result-panic/panic.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice)。 +> [Rust By Practice](https://zh.practice.rs/result-panic/panic.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/result-panic/panic.md)。 From 19aaedae36d688e172a3468a6cc0da55aeb0b2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=8F=AF?= Date: Mon, 7 Nov 2022 19:23:13 +0800 Subject: [PATCH 05/14] Update result.md --- src/basic/result-error/result.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/result-error/result.md b/src/basic/result-error/result.md index 5d93daba..d10eaae3 100644 --- a/src/basic/result-error/result.md +++ b/src/basic/result-error/result.md @@ -388,4 +388,4 @@ let x = try!(function_with_error()); ## 课后练习 -> [Rust By Practice](https://zh.practice.rs/result-panic/result.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice)。 +> [Rust By Practice](https://zh.practice.rs/result-panic/result.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/result-panic/result.md)。 From 76a1327ed5a14f70219ba3c9235beb3b1f9926ee Mon Sep 17 00:00:00 2001 From: Larry Lee Date: Tue, 8 Nov 2022 21:46:50 +0800 Subject: [PATCH 06/14] Update advance-trait.md --- src/basic/trait/advance-trait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/trait/advance-trait.md b/src/basic/trait/advance-trait.md index b469a6d9..7d8a4cd1 100644 --- a/src/basic/trait/advance-trait.md +++ b/src/basic/trait/advance-trait.md @@ -260,7 +260,7 @@ fn main() { } ``` -就像人类妈妈会给自己的宝宝起爱称一样,狗妈妈也会。狗妈妈称呼自己的宝宝为**Spot**,其它动物称呼狗宝宝为**puppy**,这个时候假如有动物不知道该称如何呼狗宝宝,它需要查询一下。 +就像人类妈妈会给自己的宝宝起爱称一样,狗妈妈也会。狗妈妈称呼自己的宝宝为**Spot**,其它动物称呼狗宝宝为**puppy**,这个时候假如有动物不知道该如何称呼狗宝宝,它需要查询一下。 `Dog::baby_name()` 的调用方式显然不行,因为这只是狗妈妈对宝宝的爱称,可能你会想到通过下面的方式查询其他动物对狗狗的称呼: From d1129906590412164bd9b11b6681b74cf6fa6fda Mon Sep 17 00:00:00 2001 From: GSLun <41274549+GSlun@users.noreply.github.com> Date: Sun, 13 Nov 2022 16:43:13 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 错误是 --> 错误时 --- src/basic/result-error/result.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/result-error/result.md b/src/basic/result-error/result.md index 5d93daba..3c1135cb 100644 --- a/src/basic/result-error/result.md +++ b/src/basic/result-error/result.md @@ -13,7 +13,7 @@ enum Result { } ``` -泛型参数 `T` 代表成功时存入的正确值的类型,存放方式是 `Ok(T)`,`E` 代表错误是存入的错误值,存放方式是 `Err(E)`,枯燥的讲解永远不及代码生动准确,因此先来看下打开文件的例子: +泛型参数 `T` 代表成功时存入的正确值的类型,存放方式是 `Ok(T)`,`E` 代表错误时存入的错误值,存放方式是 `Err(E)`,枯燥的讲解永远不及代码生动准确,因此先来看下打开文件的例子: ```rust use std::fs::File; From 0bf7783f416ee40e0a074e64bb1a85562c5d1f05 Mon Sep 17 00:00:00 2001 From: Rocky LIU <221825+rocklau@users.noreply.github.com> Date: Mon, 14 Nov 2022 19:35:59 +0800 Subject: [PATCH 08/14] Update SUMMARY.md typo --- src/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 79290554..4d925654 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -293,7 +293,7 @@ - [标准库解析 todo](std/intro.md) - - [标准库使用最佳时间 todo](std/search.md) + - [标准库使用最佳实践 todo](std/search.md) - [Vector 常用方法 todo](std/vector.md) - [HashMap todo](std/hashmap.md) - [Iterator 常用方法 todo](std/iterator.md) From de79d177470cd67d5dfd77df0e9822285fb127f7 Mon Sep 17 00:00:00 2001 From: p9s Date: Wed, 23 Nov 2022 08:52:12 +0800 Subject: [PATCH 09/14] Update concurrency-parallelism.md --- src/advance/concurrency-with-threads/concurrency-parallelism.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/advance/concurrency-with-threads/concurrency-parallelism.md b/src/advance/concurrency-with-threads/concurrency-parallelism.md index 8339c5d9..0afd54f9 100644 --- a/src/advance/concurrency-with-threads/concurrency-parallelism.md +++ b/src/advance/concurrency-with-threads/concurrency-parallelism.md @@ -41,7 +41,7 @@ #### 多核心并发 -当核心增多到 `N` 时,操作系统同时在进行的任务肯定远不止 `N` 个,这些任务将被放入 `M` 个线程队列中,接着交给 `N` 个 CPU 核心去执行,最后实现了 `M:N` 的处理模型,在这种情况下,**并发跟并行时同时在发生的,所有用户任务从表面来看都在并发的运行,其实实际上,同一时刻只有 `N` 个任务能被同时并行的处理**。 +当核心增多到 `N` 时,操作系统同时在进行的任务肯定远不止 `N` 个,这些任务将被放入 `M` 个线程队列中,接着交给 `N` 个 CPU 核心去执行,最后实现了 `M:N` 的处理模型,在这种情况下,**并发与并行是同时在发生的,所有用户任务从表面来看都在并发的运行,但实际上,同一时刻只有 `N` 个任务能被同时并行的处理**。 看到这里,相信大家已经明白两者的区别,那么我们下面给出一个正式的定义(该定义摘选自<<并发的艺术>>)。 From 9f5194abcdbb4c80b3373091904205d4b3617f93 Mon Sep 17 00:00:00 2001 From: GSLun <41274549+GSlun@users.noreply.github.com> Date: Sat, 26 Nov 2022 12:15:54 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=9C=89=E4=B8=AA?= =?UTF-8?q?=E5=B0=8F=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compiler/pitfalls/lazy-iterators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/pitfalls/lazy-iterators.md b/src/compiler/pitfalls/lazy-iterators.md index 5d51d2e0..5f0f4a3c 100644 --- a/src/compiler/pitfalls/lazy-iterators.md +++ b/src/compiler/pitfalls/lazy-iterators.md @@ -113,7 +113,7 @@ let resolvers: HashMap<_, _> = accounts ```rust let resolvers = account.into_iter().fold(HashMap::new(), |mut resolvers, a|{ - resolvers.entry(a.id).or_insert(Vec::new).push(a); + resolvers.entry(a.id).or_insert(Vec::new()).push(a); resolvers }); ``` From d396273a103576ee816302adbef3ddf74049eaee Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 27 Nov 2022 11:02:56 +0800 Subject: [PATCH 11/14] 4.1.1: fix typos --- src/async-rust/async/getting-started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/async-rust/async/getting-started.md b/src/async-rust/async/getting-started.md index 68397f40..29c648c7 100644 --- a/src/async-rust/async/getting-started.md +++ b/src/async-rust/async/getting-started.md @@ -35,7 +35,7 @@ - **Future 在 Rust 中是惰性的**,只有在被轮询(`poll`)时才会运行, 因此丢弃一个 `future` 会阻止它未来再被运行, 你可以将`Future`理解为一个在未来某个时间点被调度执行的任务。 - **Async 在 Rust 中使用开销是零**, 意味着只有你能看到的代码(自己的代码)才有性能损耗,你看不到的(`async` 内部实现)都没有性能损耗,例如,你可以无需分配任何堆内存、也无需任何动态分发来使用 `async` ,这对于热点路径的性能有非常大的好处,正是得益于此,Rust 的异步编程性能才会这么高。 -- **Rust 没有内置异步调用所必须的运行时**,但是无需担心,Rust 社区生态中已经提供了非常优异的运行时实现,例如大明星 [`tokio`](https://tokio.rs) +- **Rust 没有内置异步调用所必需的运行时**,但是无需担心,Rust 社区生态中已经提供了非常优异的运行时实现,例如大明星 [`tokio`](https://tokio.rs) - **运行时同时支持单线程和多线程**,这两者拥有各自的优缺点,稍后会讲 #### Rust: async vs 多线程 @@ -56,7 +56,7 @@ > 若大家使用 tokio,那 CPU 密集的任务尤其需要用线程的方式去处理,例如使用 `spawn_blocking` 创建一个阻塞的线程去完成相应 CPU 密集任务。 > -> 至于具体的原因,不仅是上文说到的那些,还有一个是:tokio 是协作式地调度器,如果某个 CPU 密集的异步任务是通过 tokio 创建的,那理论上来说,该异步任务需要跟其它的异步任务交错执行,最终大家都得到了执行,皆大欢喜。但实际情况是,CPU 密集的任务很可能会一直霸着着 CPU,此时 tokio 的调度方式决定了该任务会一直被执行,这意味着,其它的异步任务无法得到执行的机会,最终这些任务都会因为得不到资源而饿死。 +> 至于具体的原因,不仅是上文说到的那些,还有一个是:tokio 是协作式地调度器,如果某个 CPU 密集的异步任务是通过 tokio 创建的,那理论上来说,该异步任务需要跟其它的异步任务交错执行,最终大家都得到了执行,皆大欢喜。但实际情况是,CPU 密集的任务很可能会一直霸占着 CPU,此时 tokio 的调度方式决定了该任务会一直被执行,这意味着,其它的异步任务无法得到执行的机会,最终这些任务都会因为得不到资源而饿死。 > > 而使用 `spawn_blocking` 后,会创建一个单独的 OS 线程,该线程并不会被 tokio 所调度( 被 OS 所调度 ),因此它所执行的 CPU 密集任务也不会导致 tokio 调度的那些异步任务被饿死 From 8f24be9f83bc0815617d7e9aa62f0fa1298bfa66 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 27 Nov 2022 16:11:40 +0800 Subject: [PATCH 12/14] 6.5 fix typos --- src/test/benchmark.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/benchmark.md b/src/test/benchmark.md index cda30735..13612526 100644 --- a/src/test/benchmark.md +++ b/src/test/benchmark.md @@ -100,7 +100,7 @@ test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured; 0 filtered out; fini - 最好让 `iter` 之外的代码也具有幂等性,因为它也可能被 `benchmark` 运行多次 - 循环内的代码应该尽量的短小快速,因为这样循环才能被尽可能多的执行,结果也会更加准确 -#### 迷一般的性能结果 +#### 谜一般的性能结果 在写 `benchmark` 时,你可能会遇到一些很纳闷的棘手问题,例如以下代码: From 3a95d4a55fe016d9c23984a7be34289fb3367805 Mon Sep 17 00:00:00 2001 From: tsudzuki <93422095+LaoLittle@users.noreply.github.com> Date: Wed, 30 Nov 2022 10:54:03 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=85=A8=E6=A8=A1=E5=BC=8F=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E6=B7=BB=E5=8A=A0=E6=95=B0=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/match-pattern/all-patterns.md | 33 ++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/basic/match-pattern/all-patterns.md b/src/basic/match-pattern/all-patterns.md index 78776cf7..7c428825 100644 --- a/src/basic/match-pattern/all-patterns.md +++ b/src/basic/match-pattern/all-patterns.md @@ -97,7 +97,7 @@ Rust 知道 `'c'` 位于第一个模式的序列内,所以会打印出 `early ### 解构并分解值 -也可以使用模式来解构结构体、枚举、元组和引用。 +也可以使用模式来解构结构体、枚举、元组、数组和引用。 #### 解构结构体 @@ -274,6 +274,37 @@ let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 }); 这种将复杂类型分解匹配的方式,可以让我们单独得到感兴趣的某个值。 +#### 解构数组 + +对于数组,我们可以用类似元组的方式解构,分为两种情况: + +定长数组 +```rust +let arr: [u16; 2] = [114, 514]; +let [x, y] = arr; + +assert_eq!(x, 114); +assert_eq!(y, 514); +``` + +不定长数组 +```rust +let arr: &[u16] = &[114, 514]; + +if let [x, ..] = arr { + assert_eq!(x, &114); +} + +if let &[.., y] = arr { + assert_eq!(y, 514); +} + +let arr: &[u16] = &[]; + +assert!(matches!(arr, [..])); +assert!(!matches!(arr, [x, ..])); +``` + ### 忽略模式中的值 有时忽略模式中的一些值是很有用的,比如在 `match` 中的最后一个分支使用 `_` 模式匹配所有剩余的值。 你也可以在另一个模式中使用 `_` 模式,使用一个以下划线开始的名称,或者使用 `..` 忽略所剩部分的值。 From 60a1cb2e2ca26d286dc5ffbe20b7bc06cfbc2bc4 Mon Sep 17 00:00:00 2001 From: writey Date: Thu, 1 Dec 2022 23:00:28 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B9=A0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3=E7=AD=94=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basic/result-error/panic.md | 2 +- src/basic/result-error/result.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/result-error/panic.md b/src/basic/result-error/panic.md index 67a77416..c9904844 100644 --- a/src/basic/result-error/panic.md +++ b/src/basic/result-error/panic.md @@ -182,4 +182,4 @@ let home: IpAddr = "127.0.0.1".parse().unwrap(); ## 课后练习 -> [Rust By Practice](https://zh.practice.rs/result-panic/panic.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice)。 +> [Rust By Practice](https://zh.practice.rs/result-panic/panic.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/result-panic/panic.md)。 diff --git a/src/basic/result-error/result.md b/src/basic/result-error/result.md index 5d93daba..d10eaae3 100644 --- a/src/basic/result-error/result.md +++ b/src/basic/result-error/result.md @@ -388,4 +388,4 @@ let x = try!(function_with_error()); ## 课后练习 -> [Rust By Practice](https://zh.practice.rs/result-panic/result.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice)。 +> [Rust By Practice](https://zh.practice.rs/result-panic/result.html),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/result-panic/result.md)。