-
-
+
+
- 1132719438
+ zongzi531
|
-
-
+
+
- zongzi531
+ 1132719438
|
diff --git a/src/advance/errors.md b/src/advance/errors.md
index 7716f104..58233145 100644
--- a/src/advance/errors.md
+++ b/src/advance/errors.md
@@ -667,7 +667,25 @@ fn render() -> Result {
> 如果你想要设计自己的错误类型,同时给调用者提供具体的信息时,就使用 `thiserror`,例如当你在开发一个三方库代码时。如果你只想要简单,就使用 `anyhow`,例如在自己的应用服务中。
-本章的篇幅已经过长,因此就不具体介绍 `anyhow` 该如何使用,官方提供的例子已经足够详尽,这里就留给大家自己探索了 :)
+```rust
+use std::fs::read_to_string;
+
+use anyhow::Result;
+
+fn main() -> Result<()> {
+ let html = render()?;
+ println!("{}", html);
+ Ok(())
+}
+
+fn render() -> Result {
+ let file = std::env::var("MARKDOWN")?;
+ let source = read_to_string(file)?;
+ Ok(source)
+}
+```
+
+关于如何选用 `thiserror` 和 `anyhow` 只需要遵循一个原则即可:**是否关注自定义错误消息**,关注则使用 `thiserror`(常见业务代码),否则使用 `anyhow`(编写第三方库代码)。
## 总结
diff --git a/src/advance/unsafe/superpowers.md b/src/advance/unsafe/superpowers.md
index 1d1c650c..b56b905e 100644
--- a/src/advance/unsafe/superpowers.md
+++ b/src/advance/unsafe/superpowers.md
@@ -70,7 +70,7 @@ fn get_memory_location() -> (usize, usize) {
(pointer, length)
}
-// 在制定的内存地址读取字符串
+// 在指定的内存地址读取字符串
fn get_str_at_location(pointer: usize, length: usize) -> &'static str {
unsafe { from_utf8_unchecked(from_raw_parts(pointer as *const u8, length)) }
}
@@ -177,7 +177,7 @@ fn main() {
let r = &mut v[..];
- let (a, b) = r.split_at_mut(3);
+ let (a, b) = split_at_mut(r, 3);
assert_eq!(a, &mut [1, 2, 3]);
assert_eq!(b, &mut [4, 5, 6]);
@@ -219,6 +219,17 @@ fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
)
}
}
+
+fn main() {
+ let mut v = vec![1, 2, 3, 4, 5, 6];
+
+ let r = &mut v[..];
+
+ let (a, b) = split_at_mut(r, 3);
+
+ assert_eq!(a, &mut [1, 2, 3]);
+ assert_eq!(b, &mut [4, 5, 6]);
+}
```
相比安全实现,这段代码就显得没那么好理解了,甚至于我们还需要像 C 语言那样,通过指针地址的偏移去控制数组的分割。
diff --git a/src/async-rust/async/multi-futures-simultaneous.md b/src/async-rust/async/multi-futures-simultaneous.md
index 9e45a657..f54d1a91 100644
--- a/src/async-rust/async/multi-futures-simultaneous.md
+++ b/src/async-rust/async/multi-futures-simultaneous.md
@@ -142,7 +142,7 @@ pub fn main() {
以上代码 `default` 分支由于最后一个运行,而在它之前 `complete` 分支已经通过 `break` 跳出了循环,因此`default`永远不会被执行。
-如果你希望 `default` 也有机会漏下脸,可以将 `complete` 的 `break` 修改为其它的,例如`println!("completed!")`,然后再观察下运行结果。
+如果你希望 `default` 也有机会露下脸,可以将 `complete` 的 `break` 修改为其它的,例如`println!("completed!")`,然后再观察下运行结果。
再回到 `select` 的第一个例子中,里面有一段代码长这样:
diff --git a/src/async-rust/async/pain-points-and-workarounds.md b/src/async-rust/async/pain-points-and-workarounds.md
index 7a6a4fed..35772aef 100644
--- a/src/async-rust/async/pain-points-and-workarounds.md
+++ b/src/async-rust/async/pain-points-and-workarounds.md
@@ -35,7 +35,7 @@ error[E0282]: type annotations needed
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
```
-原因在于编译器无法推断出 `Result`中的 `E` 的类型, 而且编译器的提示`consider giving fut a type`你也别傻乎乎的相信,然后尝试半天,最后无奈放弃:目前还没有办法为 `async` 语句块指定返回类型。
+原因在于编译器无法推断出 `Result`中的 `E` 的类型, 而且编译器的提示```consider giving `fut` a type```你也别傻乎乎的相信,然后尝试半天,最后无奈放弃:目前还没有办法为 `async` 语句块指定返回类型。
既然编译器无法推断出类型,那咱就给它更多提示,可以使用 `::< ... >` 的方式来增加类型注释:
@@ -112,7 +112,7 @@ note: future is not `Send` as this value is used across an await
其中一个可能的解决方法是在 `.await` 之前就使用 `std::mem::drop` 释放掉 `Rc`,但是很可惜,截止今天,该方法依然不能解决这种问题。
-不知道有多少同学还记得语句块 `{ ... }` 在 Rust 中其实具有非常重要的作用(特别是相比其它大多数语言来说时):可以将变量声明在语句块内,当语句块结束时,变量会自动被 `drop`,这个规则可以帮助我们解决很多借用冲突问题,特别是在 `NLL` 出来之前。
+不知道有多少同学还记得语句块 `{ ... }` 在 Rust 中其实具有非常重要的作用(特别是相比其它大多数语言来说时):可以将变量声明在语句块内,当语句块结束时,变量会自动被 Drop,这个规则可以帮助我们解决很多借用冲突问题,特别是在 `NLL` 出来之前。
```rust
async fn foo() {
@@ -123,7 +123,7 @@ async fn foo() {
}
```
-是不是很简单?最终我们还是通过 `Drop` 的方式解决了这个问题,当然,还是期待未来 `std::mem::drop` 也能派上用场。
+是不是很简单?最终我们还是通过 Drop 的方式解决了这个问题,当然,还是期待未来 `std::mem::drop` 也能派上用场。
## 递归使用 async fn
@@ -166,7 +166,7 @@ error[E0733]: recursion in an `async fn` requires boxing
= note: a recursive `async fn` must be rewritten to return a boxed future.
```
-如果认真学过之前的章节,大家应该知道只要将其使用 `Box` 放到堆上而不是栈上,就可以解决,在这里还是要称赞下 Rust 的编译器,给出的提示总是这么精确`recursion in an async fn requires boxing`。
+如果认真学过之前的章节,大家应该知道只要将其使用 `Box` 放到堆上而不是栈上,就可以解决,在这里还是要称赞下 Rust 的编译器,给出的提示总是这么精确```recursion in an `async fn` requires boxing```。
就算是使用 `Box`,这里也大有讲究。如果我们试图使用 `Box::pin` 这种方式去包裹是不行的,因为编译器自身的限制限制了我们(刚夸过它。。。)。为了解决这种问题,我们只能将 `recursive` 转变成一个正常的函数,该函数返回一个使用 `Box` 包裹的 `async` 语句块:
diff --git a/src/async-rust/async/web-server.md b/src/async-rust/async/web-server.md
index 7a32a7be..c51784c0 100644
--- a/src/async-rust/async/web-server.md
+++ b/src/async-rust/async/web-server.md
@@ -52,7 +52,7 @@ fn handle_connection(mut stream: TcpStream) {
`hello.html`:
-```rust
+```html
@@ -68,7 +68,7 @@ fn handle_connection(mut stream: TcpStream) {
`404.html`:
-```rust
+```html
@@ -276,7 +276,7 @@ impl Read for MockTcpStream {
}
```
-`Write`的实现也类似,需要实现三个方法 : `poll_write`, `poll_flush`, 与 `poll_close`。 `poll_write` 会拷贝输入数据到 mock 的 `TcpStream` 中,当完成后返回 `Poll::Ready`。由于 `TcpStream` 无需 `flush` 和 `close`,因此另两个方法直接返回 `Poll::Ready` 即可.
+`Write`的实现也类似,需要实现三个方法 : `poll_write`, `poll_flush`, 与 `poll_close`。 `poll_write` 会拷贝输入数据到 mock 的 `TcpStream` 中,当完成后返回 `Poll::Ready`。由于 `TcpStream` 无需 `flush` 和 `close`,因此另两个方法直接返回 `Poll::Ready` 即可。
```rust
impl Write for MockTcpStream {
diff --git a/src/basic/base-type/numbers.md b/src/basic/base-type/numbers.md
index 535e5d86..5e8d196f 100644
--- a/src/basic/base-type/numbers.md
+++ b/src/basic/base-type/numbers.md
@@ -200,6 +200,47 @@ note: run with `RUST_BACKTRACE=1` environment variable to display
是不是**blow your mind away**? 没关系,在本书的后续章节中类似的直击灵魂的地方还很多,这就是敢号称 `Rust语言圣经(Rust Course)` 的底气!
+#### 位运算
+
+Rust的运算基本上和其他语言一样
+
+| 运算符 | 说明 |
+| ------- | -------------------------------------- |
+| & 位与 | 相同位置均为1时则为1,否则 |
+| \| 位或 | 相同位置只要有1时则为1,否则为0 |
+| ^ 异或 | 相同位置不相同则为1,相同则为0 |
+| ! 位非 | 把位中的0和1相互取反,即0置为1,1置为0 |
+| << 左移 | 所有位向左移动指定位数,右位补零 |
+| >> 右移 | 所有位向右移动指定位数,左位补零 |
+
+
+
+```rust
+fn main() {
+ // 二进制为00000010
+ let a:i32 = 2;
+ // 二进制为00000011
+ let b:i32 = 3;
+
+ println!("(a & b) value is {}", a & b);
+
+ println!("(a | b) value is {}", a | b);
+
+ println!("(a ^ b) value is {}", a ^ b);
+
+ println!("(!b) value is {} ", !b);
+
+ println!("(a << b) value is {}", a << b);
+
+ println!("(a >> b) value is {}", a >> b);
+
+ let mut a = a;
+ // 注意这些计算符除了!之外都可以加上=进行赋值 (因为!=要用来判断不等于)
+ a <<= b;
+ println!("(a << b) value is {}", a);
+}
+```
+
#### NaN
对于数学上未定义的结果,例如对负数取平方根 `-42.1.sqrt()` ,会产生一个特殊的结果:Rust 的浮点数类型使用 `NaN` (not a number)来处理这些情况。
diff --git a/src/cargo/getting-started.md b/src/cargo/getting-started.md
index bdafb2d6..a12b8d26 100644
--- a/src/cargo/getting-started.md
+++ b/src/cargo/getting-started.md
@@ -73,7 +73,7 @@ Hello, world!
`cargo run` 会帮我们自动完成编译、运行的过程,当然,该命令也支持 `Release` 模式: `cargo run --release`。
-> 如果你的程序在跑性能测试 benchmark,一定要使用 `Relase` 模式,因为该模式下,程序会做大量性能优化
+> 如果你的程序在跑性能测试 benchmark,一定要使用 `Release` 模式,因为该模式下,程序会做大量性能优化
在快速了解 `Cargo` 的使用方式后,下面,我们将正式进入 Cargo 的学习之旅。
|