ERROR HANDLING
- Rust doesn't have exceptions like other languages.
- Instead it has type Result<T, E> for recoverable error and panic macro that stops the execution when the program encounters an unrecoverable error.
fn main(){ let value: Result<&str, Box<dyn std::error::Error>> = Ok("Hello"); }
- Box is a reference to a memory in heap, in this case an error.
- You can access the values ftom result using pattern matching like given below
match value { Ok(value: &str) => println!("{}", value), Err(error: Box<dyn Error>) => println!("Error {}", error) }
- In the below code, the result will either be string or empty error, this is used if the error itself is not important:
fn main(){ let value: Result<&str, ()> = Ok("Hello"); match value { Ok(value: &str) => println!("{}", value), Err(_) => println!("Error Occured") } }
- Or you can use custom error like given below:
fn get_username() -> Result<String, ()>{ Ok("John".to_string()) } fn main(){ let username: String = get_username().expect(msg: "something went wrong");
}
- Can check if the result is an error or an ok using below methods:
fn get_username() -> Result<String, ()>{ Ok("John".to_string()) } fn main(){ let is_okay: bool = get_username().is_ok(); let is_okay: bool = get_username().is_err();
}
- You can exit early from an error like below
fn get_first_name() -> Result<String, ()>{ Ok("Sanu".to_string()) } fn get_last_name() -> Result<String, ()>{ Ok("Shilshad".to_string()) } fn get_full_name() -> Result<String, ()>{ let first_name: String = get_first_name()?; let last_name: String = get_last_name()?; Ok(format!("{} {}", first_name, last_name)) } fn main(){ let name: Result<&str, ()> = get_full_name(); match name{ Ok(value: &str) => println!("{}", value), Err(_) => println!("Error occured") }
}
In the above example in case an error occurs in get_last_name function, it propagates into the get_full_name function without breaking anything. The ? unwraps the value, only if the return type of the function is Result.
You can perform map on Result like below:
fn main(){ let name: Result<&str, ()> = get_full_name(); let length: usize = name.map(|x: String| x.len()).unwrap_or_default();
}
You can map error like below:
fn get_first_name() -> Result<String, String>{ Err("Error".to_string()) } fn get_last_name() -> Result<String, String>{ Ok("Shilshad".to_string()) } fn get_full_name() -> Result<String, String>{ let first_name: String = get_first_name()?; let last_name: String = get_last_name()?; Ok(format!("{} {}", first_name, last_name)) } fn main(){ let name: Result<String, ()> = get_full_name(); let error_length: Result<String, usize> = name.map_err(op: |e: String| e.len());
}
You can use ? in main function to unwrap if you add Result as the return type:
fn main() -> Result<(), Box<dyn std::error::Error>> { let name: String = get_full_name()?;
}
Comments
Post a Comment