Result.expect()
的控制台输出不是我需要的,所以我用我自己的版本扩展了 Result
:
trait ResultExt<T> {
fn or_exit(self, message: &str) -> T;
}
impl<T> ResultExt<T> for ::std::result::Result<T, Error> {
fn or_exit(self, message: &str) -> T {
if self.is_err() {
io::stderr().write(format!("FATAL: {} ({})\n", message, self.err().unwrap()).as_bytes()).unwrap();
process::exit(1);
}
return self.unwrap();
}
}
据我所知,Rust 还不支持可变参数,所以我必须这样使用它,对吗?
something().or_exit(&format!("Ah-ha! An error! {}", "blah"));
与 Java、Kotlin 或 C 相比,这太冗长了。解决这个问题的首选方法是什么?
最佳答案
我不认为您建议的 API 特别不符合人体工程学。如果最大性能很重要,那么将错误生成放在闭包中或为此提供 API 可能是有意义的,因此 String
仅在实际存在错误时分配,这可能特别相关当格式化某些东西特别昂贵时。 (与 std::result::Result
的所有 _else
方法一样。)
但是,您可以通过定义一个带有结果、&str
和格式参数的宏来使其更符合人体工程学。例如,这可能看起来像这样:(这是基于@E_net4 的评论)
macro_rules! or_exit {
($res:expr, $fmt:expr, $($arg:tt)+) => {
$res.unwrap_or_else(|e| {
let message = format!($fmt, $($arg)+);
eprintln!("FATAL: {} ({})\n", message, e);
process::exit(1)
})
};
}
fn main() {
let x: Result<i32, &'static str> = Err("dumb user, please replace");
let _ = or_exit!(x, "Ah-ha! An error! {}", "blahh");
}
请注意,如果用户提供无效参数,这可能不会产生最好的错误消息,我不想对您的代码进行太多更改,但是如果您决定实际上只使用糖而不是其他任何东西,您可能应该扩展您的 API采用闭包而不是字符串。您可能还想重新考虑宏的命名。
关于rust - 如何模仿效用函数的可变参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49759470/