C/C++:absl:status

本文介绍了Google内部使用的absl::Status库,用于跨API处理错误,区分可恢复和不可恢复错误。讨论了如何检查和处理错误,以及StatusOr类在成功/错误返回值中的应用。还提到忽略错误的情况和如何跟踪第一个遇到的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

absl/status目录下包含两个Status库

  • absl::Status
  • absl::StatusOr< T>

absl::Status

在 Google 内部,absl::Status 是跨 API 边界(尤其是跨 RPC 边界)优雅地处理错误的主要机制。其中一些错误可能可以恢复,但其他错误则可能无法恢复。大多数可能产生可恢复错误的函数应设计为返回一个absl::Status 或类似的absl::StatusOr< T>,它保存类型T 的对象或错误。

absl::Status MyFunction(absl::string_view filename, ...) {
  ...
  // encounter error
  if (error condition) {
    return absl::InvalidArgumentError("bad mode");
  }
  // else, return OK
  return absl::OkStatus();
}

必须被处理的返回值可以标记为ABSL_MUST_USE_RESULT

absl::Status Open(absl::string_view filename, absl::string_view mode, ...) {
  if (...) return absl::OkStatus();  // Signal success
  if (...) return absl::InvalidArgumentError("bad mode");

  absl::Status result;  // Default constructor creates an OK value as well.
  if (...) {
    // Short-hand for result = absl::Status(absl::StatusCode::kNotFound, ...)
    result = absl::NotFoundError(absl::StrCat(filename, " is missing"));
  } else {
    ...
  }
  return result;  // could be "OK" or "NOT_FOUND"
}

检查错误返回

处理多个错误代码可能会证明使用 switch 语句是合理的,但仅检查您知道如何处理的错误代码;不要尝试彻底匹配所有规范错误代码。无法处理的错误应被记录和/或传播以供更高级别处理。

如果您确实使用 switch 语句来区分状态代码,请确保还提供 default: switch 大小写,以便代码不会因将其他规范代码添加到 API 而中断。

absl::Status my_status = DoSomething();
// Don't do this:
//
//   if (my_status.code() == absl::StatusCode::kOk) { ... }
//
// Use the Status.ok() helper function:
if (!my_status.ok()) {
  LOG(WARNING) << "Unexpected error " << my_status;
}

返回一个状态或者一个值

假设函数需要在成功时返回一个值,或者在出错时返回一个状态。 Abseil Status 库为此目的提供了一个 absl::StatusOr< T> 类模板。

StatusOr<Foo> result = Calculation();
if (result.ok()) {
  result->DoSomethingCool();
} else {
  LOG(ERROR) << result.status();
}

成功后,在调用 ok() 确认 absl::StatusOr< T> 持有 T 类型的对象之后,应通过运算符 * 或运算符-> 来访问由 absl::StatusOr 持有的对象:

absl::StatusOr<int> i = GetCount();
if (i.ok()) {
  updated_total += *i;
}

像任何其他指针值一样,absl::StatusOr<T*> 可以从空指针构造,结果将是 ok() 返回 true 并且 value() 返回 nullptr。检查 absl::StatusOr 中指针的值通常需要更加小心,以确保值存在并且该值不为空:

StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
if (!result.ok()) {
  LOG(ERROR) << result.status();
} else if (*result == nullptr) {
  LOG(ERROR) << "Unexpected null pointer";
} else {
  (*result)->DoSomethingCool();
}

忽略Status Results

如果忽略函数返回的状态值,我们的编译器会产生错误。在某些情况下,忽略结果是正确的做法,您可以通过使用 IgnoreError() 来实现:

// Don't let caching errors fail the response.
StoreInCache(request, response).IgnoreError();

使用 IgnoreError() 之前请仔细考虑。除非您有充分的理由,否则更愿意实际处理返回值:也许您可以验证结果是否与您期望的错误匹配,或者您可以将其导出以进行监视。

跟踪遇到的第一个错误

例如,假设您要执行两个操作(无论第一个操作是否失败),但希望在其中一个操作失败时返回错误。代替:

absl::Status s = Operation1();
absl::Status s2 = Operation2();
if (s.ok()) s = s2;

使用下面代替

absl::Status s = Operation1();
s.Update(Operation2());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值