我最近实现了国际象棋游戏的基本机制,并使用Result<T, E>
类型收集人类输入的方法,因为它可能无效。但是,我不确定我应该选择哪种类型的可能错误(E
)。
我认为在构建图书馆时,引入新类型被认为是一种很好的做法。但是,如果可以立即处理Result
并且在stdout中报告了Err
,那么只返回Result<T, String>
或Result<T, &str>
s(或{ {1}}如果两者都可以发生?)
考虑以下情况:
Result<T, Cow<str>>
游戏在终端播放,任何输入错误都可以立即报告。在这种情况下引入自定义错误类型是否有任何附加价值?
答案 0 :(得分:8)
这是一个相当广泛的问题,没有明确的“正确”或“错误”答案。
在您的示例中需要注意的是,字符串带有很少的易于访问的语义信息。当然,您可以通过解析字符串来提取所有语义信息,但这确实是错误的方法。因此,大多数较大的库或应用程序使用带有更多语义信息的错误类型,以便于错误处理。
在你的情况下,字符串可能没问题,如果你打算立即打印它们。但是有一个巧妙的小技巧,以便至少使函数签名更具有未来性:返回Box<Error>
。
Error
trait是一个很好的抽象错误。几乎每个错误类型都实现了这个特性。使用try!()
和Into
特征,可以轻松处理大多数错误。此外:字符串和impl
有一些类型转换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())
}
请参阅working demo。
编辑:请注意,Box<Error>
的语义信息少于io::Error
等其他具体错误类型。因此,始终返回Box<Error>
并不是一个好主意!在您的情况下,这只是一种更好的方法:)
编辑2 :我最近在错误处理模型上阅读了很多,这改变了我的观点。我仍然认为这个答案非常正确。但是,我认为到目前为止,这并不像我在这里制定的那么容易。所以请记住,这个答案不适合作为一般指南在所有!