Сопоставьте результат ошибки и завершите программу при назначении переменной

#rust

#Ржавчина

Вопрос:

Я проверяю результаты функции при назначении с помощью match инструкции. В некоторых случаях я хочу выйти из программы с сообщением об ошибке, как panic!() делает. Но как я могу создать функцию или макрос, которые можно использовать везде?

Пример:

 let args = match args::Args::parse() {
    Ok(args) => args,
    Err(e) => someerror("bla")
};
let mut statedoc = match state_loader.load() {
    Ok(states) => states,
    Err(e) => someerror("blub")
};
  

Что someerror() нужно, чтобы вернуться к работе везде?

Комментарии:

1. someerror не нужно ничего возвращать, но его реализация может вызвать панику или напечатать ошибку и завершить процесс. Другими словами, вы можете вызвать panic!(s) inside someerror или, если вы не хотите, чтобы ваша программа паниковала, вы можете вызвать eprintln!("{}", s); std::process::exit(1); .

2. Нет, Rust не будет компилировать это, потому что возвращаемый тип someerror() не соответствует.

3. Это зависит от типа возвращаемого значения — см. Ответ dianhenglau.

Ответ №1:

Один из способов — использовать расходящуюся функцию. Используйте следующий синтаксис:

 fn someerror(msg: amp;str) -> ! { // Note the `-> !` here
    eprintln!("Error: {}", msg);
    panic!();
}

fn main() {
    let r: Result<i32, amp;str> = Err("hello");
    let x = match r {
        Ok(x) => x,
        Err(e) => someerror(e),
    };
    println!("x = {}", x);
}
  

Ответ №2:

Помните, что main может возвращать Result , и вы можете использовать ? -оператор везде:

 fn foo() -> Result<i32, amp;'static str> {
    Err("Nope!")
}

fn main() -> Result<(), amp;'static str> {
    let x = 5 * foo()?;
    println!("{}", x);
    Ok(())
}
  

При выполнении вышеуказанная программа просто напечатает «Ошибка: нет!» и будет иметь статус выхода, не равный нулю. Для поддержки большего количества типов ошибок у вас может быть пользовательский enum для переноса этих и соответствующих реализаций Into , так что вы можете просто сделать let args = args::Args::parse()?; . Любые ошибки будут всплывать до main() и приводить к распечатке ошибки.

Комментарии:

1. Но тогда я должен реализовать каждый тип. Я не думаю, что паника! () делает это таким образом, поскольку он не может знать каждый тип.