Handle runtime panic with try macro

时间:2015-05-26 15:41:46

标签: csv rust

I'm trying to import a CSV file using the csv crate,但问题是某些字段包含非UTF8值,因此我遇到运行时恐慌:

thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: Decode("Could not convert bytes \'FromUtf8Error { bytes: [75, 108, 105, 110, 63, 101, 107, 111, 118, 225], error: Utf8Error { valid_up_to: 9 } }\' to UTF-8.")', /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libcore/result.rs:729

这就是我的代码的样子:

extern crate csv;

fn main() {
    let mut rdr = csv::Reader::from_file("data.csv").unwrap();
    for record in rdr.decode() {
        let rec: Vec<String> = record.unwrap();
        println!("{}", rec[0]);
    }
}

我想以某种方式错误处理这种恐慌情况,所以我想知道我是否应该使用try!宏?像这样:

let rec: Vec<String> = try!(record.unwrap());

当然这会产生错误

error: the trait `rustc_serialize::serialize::Decodable` is not implemented for the type `core::result::Result<_, _>` [E0277]

正确的语法是什么?

1 个答案:

答案 0 :(得分:5)

您面临两个问题:

  1. 这不是try!宏的工作方式
  2. 您无法在try!
  3. 中使用main

    try! macro非常简单。它只是查看参数是否为Result::Err。如果是,则从当前函数返回错误。如果参数是Result::Ok,则提取内部值并且是评估try!的结果。请注意,参数必须始终为Result类型。

    第二个问题是main被定义为不返回任何值。这意味着你不能在main中使用try!,因为try!想要返回一个值。相反,您需要以“手动”的方式处理错误:

    extern crate csv;
    
    fn main() {
        let mut rdr = match csv::Reader::from_file("data.csv") {
            Ok(file) => file,
            Err(e) => println!("Put nicer error handling here"),
        };
    
        for record in rdr.decode() {
            let rec: Vec<String> = match record {
                Ok(rec) => rec,
                Err(e) => println!("Put nicer error handling here"),
            };
            println!("{}", rec[0]);
        }
    }
    
      

    我想以某种方式错误处理恐慌情况

    这是一种常见的误解。您无法处理恐慌。它们不是例外(Rust没有例外)。恐慌意味着线程死亡。你能做的最好的事情是产生一个线程并处理该线程的死亡。你真的没有做任何具体的事情。这就是Result类型的全部内容。 Result::unwrapOption::unwrap的方法意味着“如果不是{OkSome},那么现在就恐慌”。