snapshot of https://github.com/uber-go/guide.git (master, 2026-09-15; blobs > 131072B omitted)

This commit is contained in:
upstream-mirror
2026-09-15 21:54:05 +05:00
commit a9c6c3ea36
73 changed files with 8782 additions and 0 deletions

79
src/error-wrap.md Normal file
View File

@@ -0,0 +1,79 @@
# Error Wrapping
There are three main options for propagating errors if a call fails:
- return the original error as-is
- add context with `fmt.Errorf` and the `%w` verb
- add context with `fmt.Errorf` and the `%v` verb
Return the original error as-is if there is no additional context to add.
This maintains the original error type and message.
This is well suited for cases when the underlying error message
has sufficient information to track down where it came from.
Otherwise, add context to the error message where possible
so that instead of a vague error such as "connection refused",
you get more useful errors such as "call service foo: connection refused".
Use `fmt.Errorf` to add context to your errors,
picking between the `%w` or `%v` verbs
based on whether the caller should be able to
match and extract the underlying cause.
- Use `%w` if the caller should have access to the underlying error.
This is a good default for most wrapped errors,
but be aware that callers may begin to rely on this behavior.
So for cases where the wrapped error is a known `var` or type,
document and test it as part of your function's contract.
- Use `%v` to obfuscate the underlying error.
Callers will be unable to match it,
but you can switch to `%w` in the future if needed.
When adding context to returned errors, keep the context succinct by avoiding
phrases like "failed to", which state the obvious and pile up as the error
percolates up through the stack:
<table>
<thead><tr><th>Bad</th><th>Good</th></tr></thead>
<tbody>
<tr><td>
```go
s, err := store.New()
if err != nil {
return fmt.Errorf(
"failed to create new store: %w", err)
}
```
</td><td>
```go
s, err := store.New()
if err != nil {
return fmt.Errorf(
"new store: %w", err)
}
```
</td></tr><tr><td>
```plain
failed to x: failed to y: failed to create new store: the error
```
</td><td>
```plain
x: y: new store: the error
```
</td></tr>
</tbody></table>
However once the error is sent to another system, it should be clear the
message is an error (e.g. an `err` tag or "Failed" prefix in logs).
See also [Don't just check errors, handle them gracefully].
[Don't just check errors, handle them gracefully]: https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully