rust学习笔记之小练习:错误处理
错误处理
Result
pub fn gen_nametag(name: String) -> Result<String,&'static str> {
if name.is_empty() {
Err("`name` was empty; it must be nonempty.")
} else {
Ok(format!("Hi! My name is {}", name))
}
}
fn main(){
assert_eq!(gen_nametag("Beyoncé".into()), Ok("Hi! My name is Beyoncé".into()));
assert_eq!(gen_nametag("".into()),Err("`name` was empty; it must be nonempty.".into()));
}
?传播错误
use std::num::ParseIntError;
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;
let qty = item_quantity.parse::<i32>()?;
Ok(qty * cost_per_item + processing_fee)
}
fn main(){
assert_eq!(total_cost("34"), Ok(171));
assert_eq!(total_cost("beep boop").unwrap_err().to_string(),"invalid digit found in string");
let mut tokens = 100;
let pretend_user_input = "8";
let cost = total_cost(pretend_user_input);
if let Ok(cost_num)=cost {
if cost_num > tokens {
println!("You can't afford that many!");
} else {
tokens -= cost_num;
println!("You now have {} tokens.", tokens);
}
}else{
println!("ParseIntError");
}
}
Box 封装任意错误类型
use std::error;
use std::fmt;
use std::num::ParseIntError;
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
Zero,
}
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
match value {
x if x < 0 => Err(CreationError::Negative),
x if x == 0 => Err(CreationError::Zero),
x => Ok(PositiveNonzeroInteger(x as u64)),
}
}
}
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let description = match *self {
CreationError::Negative => "number is negative",
CreationError::Zero => "number is zero",
};
f.write_str(description)
}
}
impl error::Error for CreationError {}
fn parse_input(input:&str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
let x: i64 = input.parse()?;
Ok(PositiveNonzeroInteger::new(x)?)
}
fn main(){
println!("{:?}", parse_input("42").unwrap()); // PositiveNonzeroInteger(42)
println!("{}", parse_input("a b").unwrap_err()); // invalid digit found in string
println!("{}", parse_input("-1").unwrap_err()); // number is negative
println!("{}", parse_input("0").unwrap_err()); // number is zero
}
自定义错误类型
自定义错误类型,使调用者可以根据函数返回错误做判断,而不是将错误打印出来或向前传播。
use std::num::ParseIntError;
// 自定义错误类型
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
Creation(CreationError),
ParseInt(ParseIntError),
}
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> ParsePosNonzeroError {
ParsePosNonzeroError::Creation(err)
}
fn from_parseint(err: ParseIntError) -> ParsePosNonzeroError {
ParsePosNonzeroError::ParseInt(err)
}
}
fn parse_pos_nonzero(s: &str) -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> {
let x: i64 = s.parse::<i64>().map_err(ParsePosNonzeroError::from_parseint)?;
PositiveNonzeroInteger::new(x).map_err(ParsePosNonzeroError::from_creation)
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
Zero,
}
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
match value {
x if x < 0 => Err(CreationError::Negative),
x if x == 0 => Err(CreationError::Zero),
x => Ok(PositiveNonzeroInteger(x as u64)),
}
}
}
fn main(){
assert!(matches!(parse_pos_nonzero("not a number"),Err(ParsePosNonzeroError::ParseInt(_))));
assert_eq!(parse_pos_nonzero("-555"),Err(ParsePosNonzeroError::Creation(CreationError::Negative)));
assert_eq!(parse_pos_nonzero("0"),Err(ParsePosNonzeroError::Creation(CreationError::Zero)));
let x = PositiveNonzeroInteger::new(42);
assert!(x.is_ok());
assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap()));
}
Option
struct Point {
x: i32,
y: i32,
}
fn main(){
assert_eq!(maybe_icecream(9), Some(5));
assert_eq!(maybe_icecream(10), Some(5));
assert_eq!(maybe_icecream(23), Some(0));
assert_eq!(maybe_icecream(22), Some(0));
assert_eq!(maybe_icecream(25), None);
if let Some(icecreams) = maybe_icecream(12){
assert_eq!(icecreams, 5);
}
let mut range = 10;
let mut optional_integers: Vec<Option<i8>> = Vec::new();
for i in 0..(range + 1) {
optional_integers.push(Some(i));
}
while let Some(Some(integer)) = optional_integers.pop() {
assert_eq!(integer, range);
range -= 1;
}
let y: Option<Point> = Some(Point { x: 100, y: 200 });
match y {
Some(ref p) => println!("Co-ordinates are {},{} ", p.x, p.y),
_ => println!("no match"),
}
y;
}
fn maybe_icecream(time_of_day: u16) -> Option<u16> {
if time_of_day>23{
None
}else if time_of_day<22{
Some(5)
}else{
Some(0)
}
}
浙公网安备 33010602011771号