diff --git a/ChangeLog.md b/ChangeLog.md index d1e4c9f..7384cf3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,8 +1,13 @@ # ChangeLog +### 2022-3-20 + +- Add [Panics (Zh)] +- Add [Type conversion - others.md (zh)] + ### 2022-03-18 -- Add [From and Into( Zh )] +- Add [Type conversion - From and Into( Zh )] ### 2022-03-17 diff --git a/src/result-panic/intro.md b/src/result-panic/intro.md index 1b89711..193f11b 100644 --- a/src/result-panic/intro.md +++ b/src/result-panic/intro.md @@ -1,5 +1,5 @@ # Result and panic Learning resources: -- English: [Rust Book 9.1, 9.2](https://std.rs) +- English: [Rust Book 9.1, 9.2](https://doc.rust-lang.org/book/ch09-00-error-handling.html) - 简体中文: [Rust语言圣经 - 返回值和错误处理](https://course.rs/basic/result-error/intro.html) diff --git a/zh-CN/src/SUMMARY.md b/zh-CN/src/SUMMARY.md index 93e5956..bbb48ad 100644 --- a/zh-CN/src/SUMMARY.md +++ b/zh-CN/src/SUMMARY.md @@ -37,7 +37,7 @@ - [as](type-conversions/as.md) - [From/Into](type-conversions/from-into.md) - [其它转换](type-conversions/others.md) -- [返回值和 panic! todo](result-panic/intro.md) +- [返回值和 panic!](result-panic/intro.md) - [panic! 深入剖析](result-panic/panic.md) - [返回值result 和 ?](result-panic/result.md) - [包和模块 todo](crate-module/intro.md) diff --git a/zh-CN/src/result-panic/intro.md b/zh-CN/src/result-panic/intro.md index f724a70..193f11b 100644 --- a/zh-CN/src/result-panic/intro.md +++ b/zh-CN/src/result-panic/intro.md @@ -1 +1,5 @@ # Result and panic +Learning resources: +- English: [Rust Book 9.1, 9.2](https://doc.rust-lang.org/book/ch09-00-error-handling.html) +- 简体中文: [Rust语言圣经 - 返回值和错误处理](https://course.rs/basic/result-error/intro.html) + diff --git a/zh-CN/src/result-panic/panic.md b/zh-CN/src/result-panic/panic.md index b82dd9a..a9e687d 100644 --- a/zh-CN/src/result-panic/panic.md +++ b/zh-CN/src/result-panic/panic.md @@ -1 +1,111 @@ # panic! +Rust 中最简单的错误处理方式就是使用 `panic`。它会打印出一条错误信息并打印出栈调用情况,最终结束当前线程: + +- 若 panic 发生在 `main` 线程,那程序会随之退出 +- 如果是在生成的( spawn )子线程中发生 panic, 那么当前的线程会结束,但是程序依然会继续运行 + + +1. 🌟🌟 +```rust,editable + +// 填空 +fn drink(beverage: &str) { + if beverage == "lemonade" { + println!("Success!"); + // 实现下面的代码 + __ + } + + println!("Excercise Failed if printing out this line!"); +} + +fn main() { + drink(__); + + println!("Excercise Failed if printing out this line!"); +} +``` + +## 常见的 panic +2. 🌟🌟 +```rust,editable +// 修复所有的 panic,让代码工作 +fn main() { + assert_eq!("abc".as_bytes(), [96, 97, 98]); + + let v = vec![1, 2, 3]; + let ele = v[3]; + let ele = v.get(3).unwrap(); + + // 大部分时候编译器是可以帮我们提前发现溢出错误,并阻止编译通过。但是也有一些时候,这种溢出问题直到运行期才会出现 + let v = production_rate_per_hour(2); + + divide(15, 0); + + println!("Success!") +} + +fn divide(x:u8, y:u8) { + println!("{}", x / y) +} + +fn production_rate_per_hour(speed: u8) -> f64 { + let cph: u8 = 221; + match speed { + 1..=4 => (speed * cph) as f64, + 5..=8 => (speed * cph) as f64 * 0.9, + 9..=10 => (speed * cph) as f64 * 0.77, + _ => 0 as f64, + } +} + +pub fn working_items_per_minute(speed: u8) -> u32 { + (production_rate_per_hour(speed) / 60 as f64) as u32 +} +``` + +### 详细的栈调用信息 +默认情况下,栈调用只会展示最基本的信息: +```shell +thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +但是有时候,我们还希望获取更详细的信息: + +3. 🌟 +```shell +## 填空以打印全部的调用栈 +## 提示: 你可以在之前的默认 panic 信息中找到相关线索 +$ __ cargo run +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `[97, 98, 99]`, + right: `[96, 97, 98]`', src/main.rs:3:5 +stack backtrace: + 0: rust_begin_unwind + at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/std/src/panicking.rs:498:5 + 1: core::panicking::panic_fmt + at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/panicking.rs:116:14 + 2: core::panicking::assert_failed_inner + 3: core::panicking::assert_failed + at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/panicking.rs:154:5 + 4: study_cargo::main + at ./src/main.rs:3:5 + 5: core::ops::function::FnOnce::call_once + at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ops/function.rs:227:5 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. +``` + +### `unwinding` 和 `abort` + +当出现 `panic!` 时,程序提供了两种方式来处理终止流程:**栈展开**和**直接终止**。 + +其中,默认的方式就是 `栈展开`,这意味着 Rust 会回溯栈上数据和函数调用,因此也意味着更多的善后工作,好处是可以给出充分的报错信息和栈调用信息,便于事后的问题复盘。`直接终止`,顾名思义,不清理数据就直接退出程序,善后工作交与操作系统来负责。 + +对于绝大多数用户,使用默认选择是最好的,但是当你关心最终编译出的二进制可执行文件大小时,那么可以尝试去使用直接终止的方式,例如下面的配置修改 `Cargo.toml` 文件,实现在 [`release`](../first-try/cargo.md#手动编译和运行项目) 模式下遇到 `panic` 直接终止: + +```rust +[profile.release] +panic = 'abort' +``` +