Rust下MySQL查询取值与多类型错误处理优化咨询
嘿,我来帮你把这段嵌套满满的代码优化成更符合Rust风格的链式调用写法,全程避免unwrap和嵌套match,同时完整保留所有错误的安全处理逻辑~
首先,我们得确保自定义的错误枚举MyError实现了From trait,这样能自动转换各类底层错误(包括MySQL的IO超时错误),不用手动逐个匹配:
use std::error::Error; use std::fmt; use mysql; #[derive(Debug)] enum MyError { MySQL(mysql::Error), NotMatching(String), Io(std::io::Error), } // 实现Display trait让错误可以打印 impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MyError::MySQL(e) => write!(f, "MySQL查询错误: {}", e), MyError::NotMatching(msg) => write!(f, "结果不匹配: {}", msg), MyError::Io(e) => write!(f, "IO错误(含超时): {}", e), } } } // 实现Error trait让它能作为标准错误类型使用 impl Error for MyError {} // 自动把MySQL错误转成自定义错误,同时识别并转换IO错误 impl From<mysql::Error> for MyError { fn from(e: mysql::Error) -> Self { if let Some(io_err) = e.as_io_error() { MyError::Io(io_err.clone()) } else { MyError::MySQL(e) } } } // 直接转换IO错误 impl From<std::io::Error> for MyError { fn from(e: std::io::Error) -> Self { MyError::Io(e) } }
接下来是核心的查询逻辑优化。因为你的查询是WHERE id=1(主键查询,最多一行),所以我们可以直接取第一行,不用遍历整个结果集,代码更高效:
use mysql::prelude::Queryable; fn check_db_match(pool: &mysql::Pool, now: u64) -> Result<(), MyError> { // 链式调用处理整个流程:执行查询→取第一行→转换行数据→检查匹配 let db_value = pool // 执行查询,?自动把MySQL错误转成MyError .prep_exec("SELECT t FROM dbpulse_rw WHERE id=1", ())? // 获取第一行,没有行的话返回自定义错误 .next() .ok_or_else(|| MyError::NotMatching("未找到id=1的记录".into()))? // 处理行读取错误,?自动转成MyError .map_err(MyError::from)? // 转换行数据到u64,?自动处理转换错误 .and_then(|row| mysql::from_row_opt::<u64>(row).map_err(MyError::from))?; // 检查值是否匹配,不匹配返回自定义错误 if now != db_value { Err(MyError::NotMatching("记录值与预期不匹配".into())) } else { Ok(()) } }
如果你的场景确实需要遍历所有行(比如id=1可能有多行),可以用try_for_each来链式处理每一行,一旦出错立即返回:
fn check_db_match(pool: &mysql::Pool, now: u64) -> Result<(), MyError> { pool.prep_exec("SELECT t FROM dbpulse_rw WHERE id=1", ())? .try_for_each(|row| { let db_value = row? .and_then(|row| mysql::from_row_opt::<u64>(row).map_err(MyError::from))?; if now != db_value { Err(MyError::NotMatching("记录值与预期不匹配".into())) } else { Ok(()) } }) }
优化点说明:
- 利用
Fromtrait自动转换错误:不用手动嵌套match处理MySQL错误、IO错误,?操作符会自动帮我们完成转换,代码更简洁。 - 链式调用替代嵌套
match:用next()、and_then()、map_err()把逻辑拆成连续的步骤,可读性大幅提升。 - 无
unwrap,全错误安全:所有可能的错误都被显式处理,绝对不会触发panic。 - 针对主键查询优化:用
next()直接取第一行,避免不必要的迭代遍历。
内容的提问来源于stack exchange,提问作者nbari
相关产品推荐
相关产品推荐

