diff --git a/book/contents/SUMMARY.md b/book/contents/SUMMARY.md index 43fc0606..2f54c6e5 100644 --- a/book/contents/SUMMARY.md +++ b/book/contents/SUMMARY.md @@ -244,4 +244,6 @@ - [D-派生特征derive](appendix/derive.md) - [E-prelude模块 todo](appendix/prelude.md) - [F-难点索引](appendix/difficulties.md) - - [G-Rust版本发布](appendix/rust-version.md) \ No newline at end of file + - [G-Rust版本说明](appendix/rust-version.md) + - [H-Rust更新版本列表](appendix/rust-versions/intro.md) + - [1.58](appendix/rust-versions/1.58.md) \ No newline at end of file diff --git a/book/contents/appendix/rust-versions/1.58.md b/book/contents/appendix/rust-versions/1.58.md new file mode 100644 index 00000000..d17fe127 --- /dev/null +++ b/book/contents/appendix/rust-versions/1.58.md @@ -0,0 +1,80 @@ +# 1.58 + +众所周知,Rust小版本发布非常频繁,6周就发布一次,因此通常不会有特别值得普通用户关注的内容,但是这次1.58版本不同,新增了(stable化了)一个非常好用的功能:在格式化字符串时捕获环境中的值。 + +> Rust 1.58 官方 release doc: [Announcing Rust 1.58.0 | Rust Blog](https://blog.rust-lang.org/2022/01/13/Rust-1.58.0.html) + +## 在格式化字符串时捕获环境中的值 + +在以前,想要输出一个函数的返回值,你需要这么做: +```rust +fn get_person() -> String { + String::from("sunface") +} +fn main() { + let p = get_person(); + println!("Hello, {}!", p); // implicit position + println!("Hello, {0}!", p); // explicit index + println!("Hello, {person}!", person = p); +} +``` +问题倒也不大,但是一旦格式化字符串长了后,就会非常冗余,而在1.58后,我们可以这么写: +```rust +fn get_person() -> String { + String::from("sunface") +} +fn main() { + let person = get_person(); + println!("Hello, {person}!"); +} +``` +是不是清晰、简洁了很多?甚至还可以将环境中的值用于格式化参数: +```rust +let (width, precision) = get_format(); +for (name, score) in get_scores() { + println!("{name}: {score:width$.precision$}"); +} +``` +但也有局限,它只能捕获普通的变量,对于更复杂的类型(例如表达式),可以先将它赋值给一个变量或使用以前的`name = expression`形式的格式化参数。 +目前除了`panic!`外,其它接收格式化参数的宏,都可以使用新的特性。对于`panic!` 而言,如果还在使用`Rust2015`或`2018`大版本 ,那`panic!("{ident}")`依然会被当成 正常的字符串来处理,同时编译器会给予`warn`提示。而对于`2021版本`,则可以正常使用: +```rust +fn get_person() -> String { + String::from("sunface") +} +fn main() { + let person = get_person(); + panic!("Hello, {person}!"); +} +``` + +输出: +```console +thread 'main' panicked at 'Hello, sunface!', src/main.rs:6:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +## 比unwrap更危险的unwrap_unchecked + +在1.58中为`Option`和`Result`新增了`unwrap_unchecked`方法,与`unwrap`遇到错误或者空值直接`panic`不同,`unwrap_unchecked`遇到错误时处理方式糟糕的多: +```rust +fn get_num() -> Option { + None +} +fn main() { + unsafe { + let n = get_num().unwrap_unchecked(); + } +} +``` + +输出如下: +```console +zsh: segmentation fault cargo run +``` + +嗯,段错误了,对比下`panic`,有一种泪流满面的冲动:我要这不安全的方法何用? + +其实,还真有些用: + +- 想要较小的可执行文件时(嵌入式,wasm等),该方法就可以大显身手。因为panic会导致[二进制可执行文件变大不少](https://zhuanlan.zhihu.com/p/445465092) +- 它还可以提高一点性能, 因为编译器可能无法优化掉unwrap的指令分支, 虽然它只会增加区区几条分支预测指令 \ No newline at end of file diff --git a/book/contents/appendix/rust-versions/intro.md b/book/contents/appendix/rust-versions/intro.md new file mode 100644 index 00000000..56404b25 --- /dev/null +++ b/book/contents/appendix/rust-versions/intro.md @@ -0,0 +1,2 @@ +# H-Rust更新版本列表 +本目录包含了Rust历次版本更新的重要内容解读,需要注意,每个版本实际更新的内容要比这里记录的更多,全部内容请访问每节开头的官方链接查看。 \ No newline at end of file