Error Handling
-
recoverable error such as file not found, use
Result<T, E>
-
unrecoverable error such as accessing a location beyond the end of array, use
panic!
-
you can switch from unwinding to aborting upon a panic by adding panic = 'abort' to the appropriate [profile] sections in your Cargo.toml file
[profile.release] panic = 'abort'
Result type
#![allow(unused)] fn main() { enum Result<T, E> { Ok(T), Err(E), } }
Instead of
unwrap
,expect
should be used to give more context about the operation#![allow(unused)] fn main() { let file = std::fs::File::open("hello.txt") .expect("hello.txt should be included in the project") }
? operator can be used with
Result
orOption
type, but can't mix can match between them
#![allow(unused)] fn main() { // e? expression, where e is of type Result<T, E>, equals to match e { Ok(x) => x, Err(err) => { return Err(err); } } }
Sample Code
use std::fs::File; use std::io::Read; use std::io; use std::io::ErrorKind; // using panic! fn read_file(path: &str) -> io::Result<()> { let mut file = match File::open(path) { Ok(file) => file, Err(error) => panic!("Error: {:?}", error), }; let mut buf = String::new(); file.read_to_string(&mut buf)?; println!("{:?}", buf); Ok(()) } // using panic! fn read_or_create_file(path: &str) -> io::Result<()> { let mut file = File::open(path).unwrap_or_else(|error|{ if error.kind() == ErrorKind::NotFound { File::create(path).unwrap_or_else(|error| { panic!("Error creating file {:?}", error); }) } else { panic!("Error opening file"); } }); let mut buf = String::new(); file.read_to_string(&mut buf)?; println!("{:?}", buf); Ok(()) } // using Result propagation operator ? fn read_content(path: &str) -> io::Result<String> { let mut buf = String::new(); let mut f = File::open(path)?; File::read_to_string(&mut f,&mut buf)?; Ok(buf) } fn main() -> io::Result<()> { read_file("hello.txt")?; read_or_create_file("abc.txt")?; println!("{:?}", read_content("hello.txt")?); Ok(()) }