string_view
operator+
vs. StrCat()
absl::Status
std::bind
absl::optional
and std::unique_ptr
absl::StrFormat()
make_unique
and private
Constructors.bool
explicit
= delete
)switch
Statements Responsibly= delete
AbslHashValue
and Youcontains()
std::optional
parametersif
and switch
statements with initializersinline
Variablesstd::unique_ptr
Must Be MovedAbslStringify()
vector.at()
auto
for Variable Declarationsabsl::Status
Originally posted as TotW #76 on May 4, 2014
Updated 2020-02-06
Quicklink: abseil.io/tips/76
Some folks have questions about when and how to use absl::Status
, so here are
a few reasons why you ought to use Status
, and some things to keep in mind
when using it.
Use Status
to force the caller to handle the possibility of errors. Since June
2013, a function returning an Status
object cannot simply be ignored. That is,
this code produces a compilation error:
absl::Status Foo(); void CallFoo1() { Foo(); }
Whereas these calls are fine:
void CallFoo2() { Foo().IgnoreError(); } void CallFoo3() { if (!status.ok()) std::abort(); } void CallFoo4() { absl::Status status = Foo(); if (!status.ok()) LOG(ERROR) << status; }
Why is it OK for Status
to have an IgnoreError()
method, while we just went
through all this effort to make the compiler check that Status
isn’t ignored?
Imagine you’re the code reviewer looking at either CallFoo1()
or CallFoo2()
.
The latter code snippets make the reviewer think “This function could have had
an error, but the author thinks its OK to ignore it. Is it?” CallFoo1()
does
not trigger such a response.
Use Status
when it’s not clear in your code how to handle the error. Instead,
return a Status
, and let the caller, who may have more appropriate insight,
handle the error.
For example, logging locally might impact performance, such as when writing
infrastructure code. If your code is called in a tight loop, even a call to
LOG(INFO)
may be too expensive. In other cases, users may not really care if a
call succeeds, and find the log spam intrusive.
Logging is appropriate in many cases, but functions that return Status
don’t
need to LOG
to explain why something failed: they can return the failure code
and error string and let the caller decide what the right error handling
response should be.
The Google style guide famously prohibits exceptions (it’s discussed more than
any other prohibition). It can be tempting to view absl::Status
as a poor-
man’s exception mechanism, with a lot more overhead. While there may be
similarities on the surface, absl::Status
differs in its need to be explicitly
handled, rather than just passed up the stack invisibly as an unhandled
exception. It forces engineers to decide how to handle errors, and explicitly
documents that in compilable code. And finally, returning an error using a
absl::Status
is orders of magnitude faster than throwing and catching an
exception. These features may seem onerous when writing code, but the result is
a net win for everyone that has to read that code, and for Google as a whole.
Error handling is one of the easiest things to get wrong: these are inherently
the edge cases. A utility like Status
that adds consistency to error handling
across API boundaries, projects, processes, and languages helps us minimize a
large class of “There were issues with our error handling” bugs. If you’re
designing an interface that needs to express the possibility of failure, please
use Status
if you don’t have a pretty strong reason to do otherwise.