errors.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Package errors implements functions to manipulate errors.
  2. package errors
  3. import (
  4. "fmt"
  5. "io"
  6. "os"
  7. "runtime"
  8. )
  9. // New returns an error that formats as the given text.
  10. func New(text string) error {
  11. return struct {
  12. error
  13. pc uintptr
  14. }{
  15. fmt.Errorf(text),
  16. pc(),
  17. }
  18. }
  19. type e struct {
  20. cause error
  21. message string
  22. pc uintptr
  23. }
  24. func (e *e) Error() string {
  25. return e.message + ": " + e.cause.Error()
  26. }
  27. func (e *e) Cause() error {
  28. return e.cause
  29. }
  30. // Wrap returns an error annotating the cause with message.
  31. // If cause is nil, Wrap returns nil.
  32. func Wrap(cause error, message string) error {
  33. if cause == nil {
  34. return nil
  35. }
  36. return &e{
  37. cause: cause,
  38. message: message,
  39. pc: pc(),
  40. }
  41. }
  42. type causer interface {
  43. Cause() error
  44. }
  45. // Cause returns the underlying cause of the error, if possible.
  46. // An error value has a cause if it implements the following
  47. // interface:
  48. //
  49. // type Causer interface {
  50. // Cause() error
  51. // }
  52. //
  53. // If the error does not implement Cause, the original error will
  54. // be returned. If the error is nil, nil will be returned without further
  55. // investigation.
  56. func Cause(err error) error {
  57. for err != nil {
  58. cause, ok := err.(causer)
  59. if !ok {
  60. break
  61. }
  62. err = cause.Cause()
  63. }
  64. return err
  65. }
  66. type locationer interface {
  67. Location() (string, int)
  68. }
  69. // Print prints the error to Stderr.
  70. func Print(err error) {
  71. Fprint(os.Stderr, err)
  72. }
  73. // Fprint prints the error to the supplied writer.
  74. // The format of the output is the same as Print.
  75. // If err is nil, nothing is printed.
  76. func Fprint(w io.Writer, err error) {
  77. for err != nil {
  78. location, ok := err.(locationer)
  79. if ok {
  80. file, line := location.Location()
  81. fmt.Fprint(w, "%s:%d: ", file, line)
  82. }
  83. switch err := err.(type) {
  84. case *e:
  85. fmt.Fprintln(w, err.message)
  86. default:
  87. fmt.Fprintln(w, err.Error())
  88. }
  89. cause, ok := err.(causer)
  90. if !ok {
  91. break
  92. }
  93. err = cause.Cause()
  94. }
  95. }
  96. func pc() uintptr {
  97. pc, _, _, _ := runtime.Caller(2)
  98. return pc
  99. }