You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Rust新版解读 | 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<i32> {
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的指令分支 虽然它只会增加区区几条分支预测指令