To panic! or Not to panic!
In this chapter, we'll explore guidelines for choosing between panic and result.
To panic! or Not to panic!
When should you use panic! versus returning Result? Here are guidelines:
When to panic
Examples and Prototypes
When prototyping, unwrap and expect are handy placeholders:
let home = "127.0.0.1".parse().unwrap()Tests
Tests should panic on failure:
#[test]
fn test_something() {
let result = some_function()
assert_eq(result, expected_value) // Panics if not equal
}When You Have More Information
If you know the code can't fail, unwrap is fine:
let home = "127.0.0.1".parse().unwrap() // Valid IP, won't failInvalid State
Panic when continuing would be dangerous or nonsensical:
fn divide(a: int, b: int) -> int {
if b == 0 {
panic("Division by zero")
}
return a / b
}When to Return Result
Library Functions
Libraries should return Result to let callers decide how to handle errors:
fn read_file(path: string) -> Result<string, Error> {
// Return Err instead of panicking
}Expected Failure Cases
When failure is expected and recoverable:
fn find_user(id: int) -> Result<User, NotFoundError> {
// User might not exist - that's not a bug
}External Resources
When dealing with I/O, networks, etc.:
fn fetch_data(url: string) -> Result<Data, NetworkError> {
// Network might fail - caller should handle
}Summary
Use panic! for:
- Bugs (programming errors)
- Unrecoverable situations
- Tests and examples
Use Result for:
- Expected failures
- Library APIs
- Any situation the caller might want to handle
Next, let's explore Generic Types, Traits, and Lifetimes in Chapter 10.