本周小贴士#76:使用absl::status

作为TotW#76最初发表于2014年5月4日

由Titus Winters创作

更新于2020年2月6日

有些人对什么时候以及如何使用absl::Status有疑问,因此这里有一些关于你为什么应该使用Status的理由,以及在使用时应该记住的事项。

交流意图及强制调用者处理错误

使用Status强制调用者处理错误的可能性。自2013年6月以来,不能简单地忽略返回Status对象的函数。也就是说,这段代码会产生一个编译错误:

absl::Status Foo();

void CallFoo1() {
  Foo();
}

然而这些调用却很好:

void CallFoo2() {
  Foo().IgnoreError();
}

void CallFoo3() {
  if (!status.ok()) std::abort();
}

void CallFoo4() {
  absl::Status status = Foo();
  if (!status.ok()) std::cerr << status;
}

为什么Status有一个IgnoreError()方法就是可行的,然而我们通过所有努力来让编译器检查Status没有被忽略?假设你是一个代码审查员,正在查看CallFool1()或CallFoo2()。这后面的代码片段让审查员认为“这个函数可能有一个错误,但是作者认为可以忽略它,是吗?”CallFoo1()不会触发这样的响应。

允许调用者处理有更多上下文的错误

当你在代码中不能清晰地处理错误时,请使用Status。相反,返回一个Status,并且让有更合适观察力的调用者处理错误。

例如:本地记录日志可能影响性能,例如当编写一些基础架构代码时。如果你的代码是一个密集的循环中被调用,那么即便是设备std::cout的代价也是昂贵的。在其他情况,用户可能并不真地关心调用是否成功,并用发现日志垃圾邮件具有侵入性。

在许多情况下,打印日志是适合的,但是返回Status的函数不需要打印日志来解释为什么失败:它们能够返回失败码和错误字符串,让调用者决定正确地错误处理响应应该是什么。

这不就是重新发明异常吗?

谷歌风格指南以禁止异常而闻名(它的讨论比任何其他的禁止都要多)。将absl::Status视为困难户的异常机制可能很吸引人,并且有更多的开销。虽然表面上有相似之处,但是absl:Status的不同之处在需要显式处理,而不是以未处理的异常在不可见的情况下向上传递栈。它强制工程师决定如何处理错误,并且在可编译地代码中明确地记录。最后,使用absl::Status返回错误比抛出并捕获异常要快几个数量级。在写代码时,这些功能可能很繁重,但是对于每个必须阅读代码的人以及对于整个谷歌来说,这个结果是一个净胜利。

结论

错误处理是最容易出错的事情之一:这些本质上是一些边缘情况。借Status这样的程序增加跨API边界、项目、流程和语言的错误处理的一致性,以帮助我们最小化一大类“错误处理的问题”的故障。如果你设计了一个需要表达失败的接口,在你没非常充分的理由不这样做时,请使用Status。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值