关于absl::Status
用来管理处理上下文错误,在代码中可以更清晰地把错误输出在log中。返回值为absl::Status的函数,有错误时输出各种错误类型,如InternalError,NotFoundError,没有错误时输出absl::OkStatus()。
absl::Status Func(const std::string data_dir){
if (error 1){
return absl::InternalError(
absl::StrCat("Error case 1 at ", data_dir));
}
else if (error 2){
return absl::NotFoundError(
absl::StrCat("Error case 2 at ", data_dir));
}
return absl::OkStatus();
}
absl::StrCat 合并连接两个string
调用返回absl::Status的函数,有两种方式:
1 可以和RETURN_IF_ERROR一起使用,如果Func函数中有错误,外层函数会直接返回Func()的报错信息。
RETURN_IF_ERROR(Func(data_dir)) << "Failed to execute Func.";
2 如果Func(data_dir)在一个循环中,不想在外层函数中直接返回Func()的报错信息,而是跳过或者其他操作,可以用status.ok(),此时返回的是一个bool值,如果Func()没有错误,则返回true,否则返回false。
for (std::string data_dir : data_dirs){
absl::Status status = Func(data_dir);
if (!status.ok()){
// do something with the error
continue;
}
}
关于absl::StatusOr<T>
和absl::Status很相似,absl:StatusOr<>适用于有实际返回值的函数
absl::StatusOr<std::string> GetDataDir(){
if (error){
return absl::InternalError(
absl::StrCat("Error getting data dir"));
}
return "/path/to/data";
}
调用返回absl::StatusOr<T>的函数,有两种方式:
1 可以和ASSIGN_OR_RETURN一起使用,如果GetDataDir函数中有错误,外层函数会直接返回Func()的报错信息,如果没有错误,则会将GetDataDir()的返回值赋给result变量。
ASSIGN_OR_RETURN(std::string data_dir, GetDataDir());
2 可以用auto result = GetDataDir();或者直接absl::StatusOr<std::string> result = GetDataDir();
一定要在调用 ok()`确认值存在后执行,可以通过 operator*或 operator-> 访问 StatusOr 持有的值(相当于此时result是一个指针),这样是效率且安全的!
In comparison,通过absl::StatusOr::value()结合了上述两个操作:有效性测试(.ok())和值的访问。根据 value() 函数的文档,如果启用了异常,则会抛出 absl::BadStatusOrAccess 异常(该异常可以被捕获,这意味着程序可能不会终止)。如果没有启用异常,则代码将崩溃并输出 LOG(FATAL)。非必要可以避免这样用!
e.g.获取返回值,如果函数有错误,则返回absl::InternalError,否则返回"/path/to/data"。
auto get_data_dir_result = GetDataDir();
if (result.ok()){
std::cout << *get_data_dir_result;
}
使用RETURN_IF_ERROR和ASSIGN_OR_RETURN,都会在当前函数中报错时立刻退出当前函数,并且返回报错信息到上层函数,因此可以用来管理多层函数的报错信息,更容易在报错信息中定位发生错误的位置。
另外,如果返回absl::Status或absl::StatusOr<T>的函数在一个循环中,我们不想退出循环,直接返回报错,可以用res.ok()去判断instead of RETURN_IF_ERROR和ASSIGN_OR_RETURN!
注意返回absl::Status或absl::StatusOr<T>的函数,在任何情况下不能返回其他类型的值,否则直接编译报错!