- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个错误类型,它包含 Error
特征,它包装了一个潜在的错误原因,所以 source
方法返回 Some(source)
。我想知道我的错误类型上的 Display
impl 是否应该包含对该源错误的描述。
我可以看到两个选项:
source
输出中包含 Display
,例如“打开数据库时出错:没有这样的文件” "{}"
格式化就可以轻松打印整个错误链,但不可能只显示错误本身而没有底层的源错误链。此外,它使
source
方法有点毫无意义,并且让客户端代码无法选择如何格式化链中每个错误之间的格式。尽管如此,在我发现的示例代码中,这种选择似乎很常见。
source
如果它想将其包含在输出中。 Display
本身,不包括
source
。 (所以我当然有自己的。)
source
字段但没有
display
属性的错误变体默认格式化不包含
Display
的
source
输出。
source
方法的目的是什么?是为了让格式化错误链更加灵活吗?或者
Display
真的应该输出关于错误的所有用户可见的内容,而
source
只是为了开发人员可见的目的?
Error
特性的文档中。
#[derive(Debug)]
enum DatabaseError {
Opening { source: io::Error },
}
impl Error for DatabaseError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
DataBaseError::Opening { source } => Some(source),
}
}
}
impl fmt::Display for DatabaseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DatabaseError::Opening { source } => {
// ??? Should we include the source?
write!(f, "Error opening database: {}", source)
// ??? Or should we leave it to the caller to call .source()
// if they want to include that in the error description?
write!(f, "Error opening database")
}
}
}
}
最佳答案
是否在 Display
实现上打印源错误的两个选项创建了两种设计流派。
目前,尽管存在对这两种方式的看法,但两者都没有比另一个更惯用,并且最终可以在 future 找到社区范围的共识,或者在特定项目或代码库的上下文中可能已经如此。
除了 C-GOOD-ERR 之外,Rust API 指南没有对错误中的 Display
提出意见,该指南仅指出错误类型的 Display
消息应该是“小写,没有尾随标点符号,并且通常简洁”。有一个 pending proposal 来更新这个指南,指示开发人员在他们的 source
impl 中排除 Display
。同样,如果没有一些摩擦,该提案就不会存在。
在这里和现在可以做的是客观地陈述两者之间的主要区别,同时澄清一些可能的误解。
1. 是的,在你的 source
impl 中包含 Display
SNAFU 示例:
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Could not read data set token: {}", source))]
ReadToken {
#[snafu(backtrace)]
source: ReadDataSetError,
},
}
正如问题中已经提到的,关键优势是提供全部信息就像打印错误值一样简单。
eprintln!("[ERROR] {}", err);
它简单易行,不需要帮助函数来报告错误,尽管缺乏演示灵活性。如果没有字符串操作,您将得到一连串以冒号分隔的错误。
[ERROR] Could not read data set token: Could not read item value: Undefined value length of element tagged (5533,5533) at position 3548
2. 不,在你的
source
impl 上省略
Display
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Could not read data set token"))]
ReadToken {
#[snafu(backtrace)]
source: ReadDataSetError,
},
}
虽然这不会像以前那样通过单行打印为您提供完整信息,但您可以将该任务留给项目范围的错误报告者。这也为 API 的使用者提供了更大的错误呈现灵活性。
fn report<E: 'static>(err: E)
where
E: std::error::Error,
E: Send + Sync,
{
eprintln!("[ERROR] {}", err);
if let Some(cause) = err.source() {
eprintln!();
eprintln!("Caused by:");
for (i, e) in std::iter::successors(Some(cause), |e| e.source()).enumerate() {
eprintln!(" {}: {}", i, e);
}
}
}
还值得考虑与固执己见的库集成的兴趣。也就是说,生态系统中的某些 crate 可能已经对选择哪个选项做出了假设。在
anyhow
中,错误报告默认已经遍历错误的源链。当使用
anyhow
进行错误报告时,你不应该添加
source
,否则你可能会想出一个令人讨厌的重复消息列表:
[ERROR] Could not read data set token: Could not read item value: Undefined value length of element tagged (5533,5533) at position 3548
Caused by:
0: Could not read item value: Undefined value length of element tagged (5533,5533) at position 3548
1: Undefined value length of element tagged (5533,5533) at position 3548
同样,
eyre
库提供了一个可定制的错误报告抽象,但是
eyre
crate 生态系统中现有的错误报告器也假设源不是由错误的
Display
实现打印的。
source
方法的存在为所有错误类型建立了一个链状结构,可以在程序的模式匹配和后续流程控制中加以利用。
Error::source
方法在生态系统中是有目的的,不管错误是如何报告的。
关于error-handling - 源错误是否应该在显示输出中包含该源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62869360/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!