rust / intermediate
Snippet
Panic Recovery with catch_unwind
The catch_unwind function enables recovery from panics, wrapping closure execution and returning Results where Ok contains the normal result or Err contains the panic payload. AssertUnwindSafe is a marker trait indicating the closure doesn't contain resources requiring deterministic cleanup through Drop. When a panic occurs, Rust will still run destructors for Drop types during unwinding, but catch_unwind prevents the panic from propagating to the calling thread. This is valuable for隔离 dangerous code in tests or server request handling.
snippet.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::panic::{catch_unwind, AssertUnwindSafe};fn risky_operation(input: i32) -> Result<i32, String> {if input < 0 {panic!("Negative input not allowed: {}", input);}Ok(input * 2)}fn safe_wrapper() {let result = catch_unwind(AssertUnwindSafe(|| {risky_operation(-5)}));match result {Ok(Ok(value)) => println!("Success: {}", value),Ok(Err(msg)) => println!("Logic error: {}", msg),Err(_) => println!("Panic was caught!"),}}struct Resource {data: String,}impl Drop for Resource {fn drop(&mut self) {println!("Cleaning up: {}", self.data);}}fn with_cleanup() {let result = catch_unwind(AssertUnwindSafe(|| {let resource = Resource { data: String::from("allocated") };panic!("Simulated failure");}));if result.is_err() {println!("Panic caught, destructor still ran");}}fn main() {safe_wrapper();with_cleanup();}
Breakdown
1
catch_unwind(AssertUnwindSafe(||
Wrapper for recoverable panic detection
2
Ok(Ok(value))
Triple nested: no panic, no error, contains value
3
Err(_) => println!("Panic was caught!")
Panic payload caught, thread continues
4
struct Resource impl Drop
Destructor guarantee even during panic unwinding
5
result.is_err()
Check if panic occurred without reading payload