You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 2.4 KiB

1 year ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. # errwrap
  2. `errwrap` is a package for Go that formalizes the pattern of wrapping errors
  3. and checking if an error contains another error.
  4. There is a common pattern in Go of taking a returned `error` value and
  5. then wrapping it (such as with `fmt.Errorf`) before returning it. The problem
  6. with this pattern is that you completely lose the original `error` structure.
  7. Arguably the _correct_ approach is that you should make a custom structure
  8. implementing the `error` interface, and have the original error as a field
  9. on that structure, such [as this example](http://golang.org/pkg/os/#PathError).
  10. This is a good approach, but you have to know the entire chain of possible
  11. rewrapping that happens, when you might just care about one.
  12. `errwrap` formalizes this pattern (it doesn't matter what approach you use
  13. above) by giving a single interface for wrapping errors, checking if a specific
  14. error is wrapped, and extracting that error.
  15. ## Installation and Docs
  16. Install using `go get github.com/hashicorp/errwrap`.
  17. Full documentation is available at
  18. http://godoc.org/github.com/hashicorp/errwrap
  19. ## Usage
  20. #### Basic Usage
  21. Below is a very basic example of its usage:
  22. ```go
  23. // A function that always returns an error, but wraps it, like a real
  24. // function might.
  25. func tryOpen() error {
  26. _, err := os.Open("/i/dont/exist")
  27. if err != nil {
  28. return errwrap.Wrapf("Doesn't exist: {{err}}", err)
  29. }
  30. return nil
  31. }
  32. func main() {
  33. err := tryOpen()
  34. // We can use the Contains helpers to check if an error contains
  35. // another error. It is safe to do this with a nil error, or with
  36. // an error that doesn't even use the errwrap package.
  37. if errwrap.Contains(err, "does not exist") {
  38. // Do something
  39. }
  40. if errwrap.ContainsType(err, new(os.PathError)) {
  41. // Do something
  42. }
  43. // Or we can use the associated `Get` functions to just extract
  44. // a specific error. This would return nil if that specific error doesn't
  45. // exist.
  46. perr := errwrap.GetType(err, new(os.PathError))
  47. }
  48. ```
  49. #### Custom Types
  50. If you're already making custom types that properly wrap errors, then
  51. you can get all the functionality of `errwraps.Contains` and such by
  52. implementing the `Wrapper` interface with just one function. Example:
  53. ```go
  54. type AppError {
  55. Code ErrorCode
  56. Err error
  57. }
  58. func (e *AppError) WrappedErrors() []error {
  59. return []error{e.Err}
  60. }
  61. ```
  62. Now this works:
  63. ```go
  64. err := &AppError{Err: fmt.Errorf("an error")}
  65. if errwrap.ContainsType(err, fmt.Errorf("")) {
  66. // This will work!
  67. }
  68. ```