用Box< error :: Error>装箱后如何处理不同的错误类型? [英] How to handle different error types after boxing them with Box<error::Error>?

查看:33
本文介绍了用Box< error :: Error>装箱后如何处理不同的错误类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了更好地处理错误并防止重复代码,我正在实施

In my try to better handle errors and prevent repeating tio much code, I am implementing the ?, operator returning Result<bool, Box<error::Error>> so that I could just match the error once instead of multiple times.

我使用多个 match es更改了以下代码:

I changed the following code using multiple matches:

fn example(pool: mysql::Pool) {
    let now = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
        Ok(n) => n.as_secs(),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    };

    // create table
    match pool.prep_exec("CREATE TABLE IF NOT EXISTS dbpulse_rw (id INT NOT NULL, t INT(11) NOT NULL, PRIMARY KEY(id))", ()) {
        Ok(_) => (),
        Err(e) => {
            eprintln!("{}", e);
            return;
        }
    }

    // write into table
    let mut stmt = match pool
        .prepare("INSERT INTO dbpulse_rw (id, t) VALUES (1, ?) ON DUPLICATE KEY UPDATE t=?")
    {
        Ok(stmt) => stmt,
        Err(e) => {
            eprintln!("{}", e);
            return;
        }
    };

    match stmt.execute((now, now)) {
        Ok(_) => (),
        Err(mysql::Error::IoError(e)) => {
            eprintln!("IoError: {}", e);
            // send alert
            return;
        }
        Err(e) => {
            eprintln!("{}", e);
            return;
        }
    }

    let items = match pool.prep_exec("SELECT t FROM dbpulse_rw WHERE id=1", ()) {
        Ok(n) => n,
        Err(mysql::Error::IoError(e)) => {
            eprintln!("IoError: {}", e);
            //send_alert
            return;
        }
        Err(e) => {
            eprintln!("{}", e);
            return;
        }
    };
    for row in items {
        let pool = pool.clone();
        let rs = mysql::from_row::<u64>(row.unwrap());
        if now != rs {
            // send alert
        }
        assert_eq!(now, rs);
    }
}

要使用?运算符,请执行以下操作:

To use the ? operator:

fn example(pool: mysql::Pool) -> Result<bool, Box<error::Error>> {
    let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
    let now = n.as_secs();

    // create table
    pool.prep_exec("CREATE TABLE IF NOT EXISTS dbpulse_rw (id INT NOT NULL, t INT(11) NOT NULL, PRIMARY KEY(id))", ())?;

    // write into table
    let mut stmt = pool
        .prepare("INSERT INTO dbpulse_rw (id, t) VALUES (1, ?) ON DUPLICATE KEY UPDATE t=?")?;
    stmt.execute((now, now))?;

    pool.prep_exec("SELECT t FROM dbpulse_rw WHERE id=1", ())
        .map(|items| {
            for row in items {
                match row {
                    Ok(row) => {
                        let rs = mysql::from_row::<u64>(row);
                        if now != rs {
                            // send alert
                        }
                    }
                    Err(e) => println!("{}", e),
                }
            }
        })?;

    Ok(true)
}

我现在想做的是根据错误(超时或查询错误或其他错误类型)进行 match 匹配.我正在这样创建MySQL池:

What I would like to do now is to match based on the error, either a timeout or a query error, or other error type. I am creating the MySQL pool like this:

let mut opts = mysql::OptsBuilder::from_opts(dsn);
opts.stmt_cache_size(0);
opts.read_timeout(Some(Duration::new(3, 0)));
opts.write_timeout(Some(Duration::new(3, 0)));
let pool = mysql::Pool::new_manual(1, 5, opts).expect("Could not connect to MySQL");

如果查询花费了3秒钟以上的时间,它将返回 mysql :: Error :: IoError ,我想在其他可能的错误之间进行区分,到目前为止,我已经尝试过:

If a query takes more than 3 seconds it will return a mysql::Error::IoError the one I would like to distinguish between other possible errors, so far I have tried:

fun run_example() {
    match example() {
       Ok(_) => (),
       Err(mysql::Error::IoError(e)) => {
          eprintln!("IoError: {}", e);
          // send alert
          return;
       }
       Err(e) => {
         eprintln!("{}", e);
         return;
       }
    }
}

但是我收到类型不匹配的错误:

But I am getting a mismatched types error:

expected struct `std::boxed::Box`, found enum `mysql::error::Error`

有关如何实施此操作的任何提示或更好的主意?

Any tips or better ideas about how to implement this?

推荐答案

使用特质会丢失具体的类型信息.某些错误包装箱可能会对您有所帮助,但这意味着将特征转换为具体类型,因此在运行时可能会失败.

You lose the concrete type information by using a trait. Some error crate could help you, but this implies casting a trait to a concrete type and so could fail at runtime.

我建议您创建一个 MyError 类型,并列出您的函数可能产生的所有潜在错误.然后,您可以很好,快速地匹配实际错误.例如,使用 SNAFU

I advise you to create a type MyError and list all potential errors that your function could produce. You can then match the real error nicely and fast. For example, use SNAFU

这篇关于用Box&lt; error :: Error&gt;装箱后如何处理不同的错误类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆