我最近实现了国际象棋的基本机制,并将这种Result<T, E>
类型用于收集人类输入的方法,因为这可能是无效的。但是,我不确定应该为错误(E
)选择哪种类型。
我已经收集到,在构建库时,引入新类型被认为是一种好习惯。但是,当Result
可以立即处理并Err
在stdout中报告时,仅返回Result<T, String>
s或Result<T, &str>
s(Result<T, Cow<str>>
如果同时出现s或s)是否更简单?
考虑以下情况:
pub fn play() {
let mut game = Game::new();
loop {
match game.turn() {
Ok(()) => { game.turn += 1 }
Err(e) => println!("{}", e)
}
}
}
游戏在终端上进行,任何输入错误都可以立即报告。在这种情况下,引入自定义错误类型是否有任何附加值?
这是一个相当广泛的问题,没有明确的“正确”或“错误”答案。
在您的示例中需要注意的重要一点是,字符串几乎不包含任何易于访问的语义信息。当然,您可以通过解析字符串来提取所有语义信息,但这确实是错误的方法。因此,大多数较大的库或应用程序都使用带有更多语义信息的错误类型,以简化错误处理。
在您的情况下,如果您仍然可以立即打印字符串,则字符串可能就可以了。但是,有一个巧妙的小技巧,以便至少使函数签名更富未来性:returnBox<Error>
。
的Error
特点是在错误的一个很好的抽象。几乎每种错误类型都实现了此特征。利用try!()
和Into
特性,可以轻松处理大多数错误。此外:有一些impl
用于string和的类型转换Box<Error>
。这允许将字符串作为错误返回:
fn foo() -> Result<(), Box<Error>> {
try!(std::fs::File::open("not-here")); // io::Error
try!(Err("oh noooo!")); // &str
try!(Err("I broke it :<".to_owned())); // String
Err("nop".into())
}
请参阅工作演示。
编辑:请注意,它Box<Error>
携带的语义信息比其他具体错误类型(如)少io::Error
。因此,总是回来不是一个好主意Box<Error>
!这只是您情况下的一种更好的方法:)
编辑2:最近,我已经阅读了很多有关错误处理模型的信息,这使我的看法有所改变。我仍然认为这个答案几乎是正确的。但是,我认为这远不如我在这里制定的那么容易。所以,一定要记住这个答案不适合作为一般的指导可言!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句