简化Rust中的验证逻辑:优化双变量非空及无问号检查
优化你的Rust验证代码
原代码能实现需求,但有不少可以贴合Rust惯用写法的优化点,先上改进后的代码,再拆解优化细节:
#[derive(Debug)] pub enum TestError { ContainsQuestionMark, NullInput, } pub type TestResult = Result<(), TestError>; fn main() { let x = Some(String::from("x")); let y = Some(String::from("y")); match (x.as_ref(), y.as_ref()) { (Some(x_str), Some(y_str)) => { if let Err(TestError::ContainsQuestionMark) = validate(x_str, y_str) { println!("x or y contains ?"); return; } out(x_str, y_str); } _ => { println!("x and y are Null"); return; } } } fn validate(x: &str, y: &str) -> TestResult { if x.contains('?') || y.contains('?') { return Err(TestError::ContainsQuestionMark); } Ok(()) } fn out(x: &str, y: &str) { println!("These are x = {x}, y = {y}"); }
核心优化点
- 去掉冗余的克隆与unwrap:原代码先判断
is_some()再clone().unwrap()完全没必要,用as_ref()将Option<String>转为Option<&String>,再通过模式匹配直接拿到引用,避免了无意义的内存拷贝。 - 优化错误类型与返回值:
- 给
TestError新增NullInput枚举值,让错误类型更清晰,后续扩展也更方便; validate函数返回Result<(), TestError>而非Result<bool, TestError>——验证成功不需要传递额外值,Ok(())足够表达成功状态,更符合Rust错误处理的设计思路。
- 给
- 参数类型更通用:把
validate和out的参数从&String改成&str,&String会自动 Deref 为&str,这样函数不仅能接收字符串引用,还能兼容字符串字面量等其他实现Deref<Target=str>的类型。 - 移除不必要的进程退出:原
out函数里的std::process::exit(0)完全多余,main函数正常执行完毕就会返回0退出,手动调用反而画蛇添足。 - 用模式匹配替代嵌套if:通过
match (x.as_ref(), y.as_ref())直接匹配两个Option的状态,代码结构更扁平,可读性更强。 - 字符匹配更高效:把
contains("?")改成contains('?'),前者匹配字符串,后者匹配单个字符,性能更优。
更简洁的错误处理写法
如果想进一步简化代码,可以让main函数返回Result,用?操作符自动处理错误:
#[derive(Debug)] pub enum TestError { ContainsQuestionMark, NullInput, } pub type TestResult = Result<(), TestError>; fn main() { if let Err(e) = inner_main() { match e { TestError::NullInput => println!("x and y are Null"), TestError::ContainsQuestionMark => println!("x or y contains ?"), } } } fn inner_main() -> TestResult { let x = Some(String::from("x")); let y = Some(String::from("y")); // 把Option转为Result,用?自动处理空值错误 let (x_str, y_str) = x.as_ref() .and_then(|x_val| y.as_ref().map(|y_val| (x_val, y_val))) .ok_or(TestError::NullInput)?; validate(x_str, y_str)?; out(x_str, y_str); Ok(()) } fn validate(x: &str, y: &str) -> TestResult { if x.contains('?') || y.contains('?') { Err(TestError::ContainsQuestionMark) } else { Ok(()) } } fn out(x: &str, y: &str) { println!("These are x = {x}, y = {y}"); }
这种写法把业务逻辑和错误展示分离,代码更简洁,完全去掉了嵌套判断,是Rust中处理这类场景的惯用方式。
内容的提问来源于stack exchange,提问作者MarieGosnell
相关产品推荐
相关产品推荐

