如果成功,从没有结果的函数返回错误的惯用方法是啥?
Posted
技术标签:
【中文标题】如果成功,从没有结果的函数返回错误的惯用方法是啥?【英文标题】:What is the idiomatic way to return an error from a function with no result if successful?如果成功,从没有结果的函数返回错误的惯用方法是什么? 【发布时间】:2016-08-21 01:20:32 【问题描述】:在 Rust 中,我认为处理可恢复错误的惯用方法是使用 Result。例如这个函数显然是惯用的:
fn do_work() -> Result<u64, WorkError> ...
当然,也有一些函数具有单一的、明显的失败状态,因此使用 Option 类型来代替。一个惯用的例子是这样的:
fn do_work() -> Option<u64>
这一切都在文档中直接解决。但是,我对函数可能失败但成功时没有意义的情况感到困惑。比较以下两个函数:
fn do_work() -> Option<WorkError>
// vs
fn do_work() -> Result<(), WorkError>
我只是不确定其中哪一个更惯用,或者在现实世界的 Rust 代码中更常用。对于此类问题,我的首选资源是 Rust 书,但我认为它的“Error Handling”部分没有解决这个问题。我对任何其他 Rust 文档也没有太多运气。
当然,这似乎很主观,但我正在寻找权威来源,要么说明哪种形式是惯用的,要么说明为什么一种形式优于(或低于)另一种形式。 (我也很好奇该约定与其他大量使用“错误作为值”的语言相比如何,例如 Go 和 Haskell。)
【问题讨论】:
我属于Result<(), Error>
的一方。我通常也将这些别名为我自己的类型。我很想听听别人怎么说。不过我这样做是因为 try!
宏仍然可以很好地配合它。
【参考方案1】:
Rust 是“非常强类型化的”(请不要告诉我我如何衡量一种语言的强类型化程度......)。我的意思是说,Rust 通常为您提供让类型为您“说话”并记录您的代码的工具,因此使用此功能编写可读代码是惯用的。
换句话说,您要问的问题应该是“哪种类型最能代表函数对读取其签名的任何人的作用?”
对于Result<(), Workerror>
你可以直接看到from the docs
Result 是表示成功(Ok)或失败(Err)的类型
因此,专门针对您的情况,这意味着您的函数在成功时不返回任何内容(由Ok<()>
表示)或在出现错误时返回WorkError
(Err<WorkError>
)。这是您在问题中描述函数的方式的代码中非常直接的表示。
将此与Option<WorkError>
或Option<()>
进行比较
Type Option 表示一个可选值:每个 Option 要么是 Some 并且包含一个值,要么是 None,并且没有
在你的情况下,Option<WorkError>
会对读者说“这个函数应该返回一个 WorkError
但它可能什么也不返回”。您可以记录下“不返回任何内容”的情况意味着该函数实际上是成功的,但这仅从类型上并不是很明显。
Option<()>
说“这个函数可以不返回任何内容或没有任何有意义的返回”,如果WorkError
不包含其他信息(如错误类型或错误消息)并且实际上只是一种说“发生错误”的方式。在这种情况下,一个简单的bool
携带相同的信息...否则Result
允许您返回与错误相关的更多信息。
【讨论】:
【参考方案2】:使用fn do_work() -> Result<(), WorkError>
。
Result<(), WorkError>
表示你希望工作完成,但它可能会失败。
Option<WorkError>
表示你想得到一个错误,但它可能不存在。
写do_work()
时,您可能希望工作完成但又不想出错,因此Result<(), WorkError>
是更好的选择。
我希望Option<WorkError>
仅用于fn get_last_work_error() -> Option<WorkError>
之类的情况。
【讨论】:
我不认为我不同意,我认为 Result 稍微好一点。但是,我想知道是否有任何“官方”资源以任何方式支持您的回答? @Others 因为do_work
本身就是一个概念性的例子,我不认为会有任何官方约定。但是你可以对标准库中的成语有所了解,例如:doc.rust-lang.org/nightly/std/io/…
@Others 当一个可能失败的操作没有返回任何有用的东西(例如std::io
和std::fs
的许多函数)时,整个标准库普遍使用Result<(), _>
。这是正确的选择。
@Others,使用 Result
在 aturon.github.io/errors/signaling.html#obstructions 得到正式认可(根据 RFC 236)。
@ArtemGr 请注意,该页面中讨论的替代方案将是 OP 问题上下文中的 Option<()>
,而不是 Option<WorkError>
。前者None
表示工作未正常完成,而后者None
表示工作正常。以上是关于如果成功,从没有结果的函数返回错误的惯用方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章