error.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. // Copyright (c) 2017-2021 Uber Technologies, Inc.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. // Package multierr allows combining one or more errors together.
  21. //
  22. // # Overview
  23. //
  24. // Errors can be combined with the use of the Combine function.
  25. //
  26. // multierr.Combine(
  27. // reader.Close(),
  28. // writer.Close(),
  29. // conn.Close(),
  30. // )
  31. //
  32. // If only two errors are being combined, the Append function may be used
  33. // instead.
  34. //
  35. // err = multierr.Append(reader.Close(), writer.Close())
  36. //
  37. // The underlying list of errors for a returned error object may be retrieved
  38. // with the Errors function.
  39. //
  40. // errors := multierr.Errors(err)
  41. // if len(errors) > 0 {
  42. // fmt.Println("The following errors occurred:", errors)
  43. // }
  44. //
  45. // # Appending from a loop
  46. //
  47. // You sometimes need to append into an error from a loop.
  48. //
  49. // var err error
  50. // for _, item := range items {
  51. // err = multierr.Append(err, process(item))
  52. // }
  53. //
  54. // Cases like this may require knowledge of whether an individual instance
  55. // failed. This usually requires introduction of a new variable.
  56. //
  57. // var err error
  58. // for _, item := range items {
  59. // if perr := process(item); perr != nil {
  60. // log.Warn("skipping item", item)
  61. // err = multierr.Append(err, perr)
  62. // }
  63. // }
  64. //
  65. // multierr includes AppendInto to simplify cases like this.
  66. //
  67. // var err error
  68. // for _, item := range items {
  69. // if multierr.AppendInto(&err, process(item)) {
  70. // log.Warn("skipping item", item)
  71. // }
  72. // }
  73. //
  74. // This will append the error into the err variable, and return true if that
  75. // individual error was non-nil.
  76. //
  77. // See [AppendInto] for more information.
  78. //
  79. // # Deferred Functions
  80. //
  81. // Go makes it possible to modify the return value of a function in a defer
  82. // block if the function was using named returns. This makes it possible to
  83. // record resource cleanup failures from deferred blocks.
  84. //
  85. // func sendRequest(req Request) (err error) {
  86. // conn, err := openConnection()
  87. // if err != nil {
  88. // return err
  89. // }
  90. // defer func() {
  91. // err = multierr.Append(err, conn.Close())
  92. // }()
  93. // // ...
  94. // }
  95. //
  96. // multierr provides the Invoker type and AppendInvoke function to make cases
  97. // like the above simpler and obviate the need for a closure. The following is
  98. // roughly equivalent to the example above.
  99. //
  100. // func sendRequest(req Request) (err error) {
  101. // conn, err := openConnection()
  102. // if err != nil {
  103. // return err
  104. // }
  105. // defer multierr.AppendInvoke(&err, multierr.Close(conn))
  106. // // ...
  107. // }
  108. //
  109. // See [AppendInvoke] and [Invoker] for more information.
  110. //
  111. // NOTE: If you're modifying an error from inside a defer, you MUST use a named
  112. // return value for that function.
  113. //
  114. // # Advanced Usage
  115. //
  116. // Errors returned by Combine and Append MAY implement the following
  117. // interface.
  118. //
  119. // type errorGroup interface {
  120. // // Returns a slice containing the underlying list of errors.
  121. // //
  122. // // This slice MUST NOT be modified by the caller.
  123. // Errors() []error
  124. // }
  125. //
  126. // Note that if you need access to list of errors behind a multierr error, you
  127. // should prefer using the Errors function. That said, if you need cheap
  128. // read-only access to the underlying errors slice, you can attempt to cast
  129. // the error to this interface. You MUST handle the failure case gracefully
  130. // because errors returned by Combine and Append are not guaranteed to
  131. // implement this interface.
  132. //
  133. // var errors []error
  134. // group, ok := err.(errorGroup)
  135. // if ok {
  136. // errors = group.Errors()
  137. // } else {
  138. // errors = []error{err}
  139. // }
  140. package multierr // import "go.uber.org/multierr"
  141. import (
  142. "bytes"
  143. "errors"
  144. "fmt"
  145. "io"
  146. "strings"
  147. "sync"
  148. "go.uber.org/atomic"
  149. )
  150. var (
  151. // Separator for single-line error messages.
  152. _singlelineSeparator = []byte("; ")
  153. // Prefix for multi-line messages
  154. _multilinePrefix = []byte("the following errors occurred:")
  155. // Prefix for the first and following lines of an item in a list of
  156. // multi-line error messages.
  157. //
  158. // For example, if a single item is:
  159. //
  160. // foo
  161. // bar
  162. //
  163. // It will become,
  164. //
  165. // - foo
  166. // bar
  167. _multilineSeparator = []byte("\n - ")
  168. _multilineIndent = []byte(" ")
  169. )
  170. // _bufferPool is a pool of bytes.Buffers.
  171. var _bufferPool = sync.Pool{
  172. New: func() interface{} {
  173. return &bytes.Buffer{}
  174. },
  175. }
  176. type errorGroup interface {
  177. Errors() []error
  178. }
  179. // Errors returns a slice containing zero or more errors that the supplied
  180. // error is composed of. If the error is nil, a nil slice is returned.
  181. //
  182. // err := multierr.Append(r.Close(), w.Close())
  183. // errors := multierr.Errors(err)
  184. //
  185. // If the error is not composed of other errors, the returned slice contains
  186. // just the error that was passed in.
  187. //
  188. // Callers of this function are free to modify the returned slice.
  189. func Errors(err error) []error {
  190. if err == nil {
  191. return nil
  192. }
  193. // Note that we're casting to multiError, not errorGroup. Our contract is
  194. // that returned errors MAY implement errorGroup. Errors, however, only
  195. // has special behavior for multierr-specific error objects.
  196. //
  197. // This behavior can be expanded in the future but I think it's prudent to
  198. // start with as little as possible in terms of contract and possibility
  199. // of misuse.
  200. eg, ok := err.(*multiError)
  201. if !ok {
  202. return []error{err}
  203. }
  204. return append(([]error)(nil), eg.Errors()...)
  205. }
  206. // multiError is an error that holds one or more errors.
  207. //
  208. // An instance of this is guaranteed to be non-empty and flattened. That is,
  209. // none of the errors inside multiError are other multiErrors.
  210. //
  211. // multiError formats to a semi-colon delimited list of error messages with
  212. // %v and with a more readable multi-line format with %+v.
  213. type multiError struct {
  214. copyNeeded atomic.Bool
  215. errors []error
  216. }
  217. var _ errorGroup = (*multiError)(nil)
  218. // Errors returns the list of underlying errors.
  219. //
  220. // This slice MUST NOT be modified.
  221. func (merr *multiError) Errors() []error {
  222. if merr == nil {
  223. return nil
  224. }
  225. return merr.errors
  226. }
  227. // As attempts to find the first error in the error list that matches the type
  228. // of the value that target points to.
  229. //
  230. // This function allows errors.As to traverse the values stored on the
  231. // multierr error.
  232. func (merr *multiError) As(target interface{}) bool {
  233. for _, err := range merr.Errors() {
  234. if errors.As(err, target) {
  235. return true
  236. }
  237. }
  238. return false
  239. }
  240. // Is attempts to match the provided error against errors in the error list.
  241. //
  242. // This function allows errors.Is to traverse the values stored on the
  243. // multierr error.
  244. func (merr *multiError) Is(target error) bool {
  245. for _, err := range merr.Errors() {
  246. if errors.Is(err, target) {
  247. return true
  248. }
  249. }
  250. return false
  251. }
  252. func (merr *multiError) Error() string {
  253. if merr == nil {
  254. return ""
  255. }
  256. buff := _bufferPool.Get().(*bytes.Buffer)
  257. buff.Reset()
  258. merr.writeSingleline(buff)
  259. result := buff.String()
  260. _bufferPool.Put(buff)
  261. return result
  262. }
  263. func (merr *multiError) Format(f fmt.State, c rune) {
  264. if c == 'v' && f.Flag('+') {
  265. merr.writeMultiline(f)
  266. } else {
  267. merr.writeSingleline(f)
  268. }
  269. }
  270. func (merr *multiError) writeSingleline(w io.Writer) {
  271. first := true
  272. for _, item := range merr.errors {
  273. if first {
  274. first = false
  275. } else {
  276. w.Write(_singlelineSeparator)
  277. }
  278. io.WriteString(w, item.Error())
  279. }
  280. }
  281. func (merr *multiError) writeMultiline(w io.Writer) {
  282. w.Write(_multilinePrefix)
  283. for _, item := range merr.errors {
  284. w.Write(_multilineSeparator)
  285. writePrefixLine(w, _multilineIndent, fmt.Sprintf("%+v", item))
  286. }
  287. }
  288. // Writes s to the writer with the given prefix added before each line after
  289. // the first.
  290. func writePrefixLine(w io.Writer, prefix []byte, s string) {
  291. first := true
  292. for len(s) > 0 {
  293. if first {
  294. first = false
  295. } else {
  296. w.Write(prefix)
  297. }
  298. idx := strings.IndexByte(s, '\n')
  299. if idx < 0 {
  300. idx = len(s) - 1
  301. }
  302. io.WriteString(w, s[:idx+1])
  303. s = s[idx+1:]
  304. }
  305. }
  306. type inspectResult struct {
  307. // Number of top-level non-nil errors
  308. Count int
  309. // Total number of errors including multiErrors
  310. Capacity int
  311. // Index of the first non-nil error in the list. Value is meaningless if
  312. // Count is zero.
  313. FirstErrorIdx int
  314. // Whether the list contains at least one multiError
  315. ContainsMultiError bool
  316. }
  317. // Inspects the given slice of errors so that we can efficiently allocate
  318. // space for it.
  319. func inspect(errors []error) (res inspectResult) {
  320. first := true
  321. for i, err := range errors {
  322. if err == nil {
  323. continue
  324. }
  325. res.Count++
  326. if first {
  327. first = false
  328. res.FirstErrorIdx = i
  329. }
  330. if merr, ok := err.(*multiError); ok {
  331. res.Capacity += len(merr.errors)
  332. res.ContainsMultiError = true
  333. } else {
  334. res.Capacity++
  335. }
  336. }
  337. return
  338. }
  339. // fromSlice converts the given list of errors into a single error.
  340. func fromSlice(errors []error) error {
  341. // Don't pay to inspect small slices.
  342. switch len(errors) {
  343. case 0:
  344. return nil
  345. case 1:
  346. return errors[0]
  347. }
  348. res := inspect(errors)
  349. switch res.Count {
  350. case 0:
  351. return nil
  352. case 1:
  353. // only one non-nil entry
  354. return errors[res.FirstErrorIdx]
  355. case len(errors):
  356. if !res.ContainsMultiError {
  357. // Error list is flat. Make a copy of it
  358. // Otherwise "errors" escapes to the heap
  359. // unconditionally for all other cases.
  360. // This lets us optimize for the "no errors" case.
  361. out := append(([]error)(nil), errors...)
  362. return &multiError{errors: out}
  363. }
  364. }
  365. nonNilErrs := make([]error, 0, res.Capacity)
  366. for _, err := range errors[res.FirstErrorIdx:] {
  367. if err == nil {
  368. continue
  369. }
  370. if nested, ok := err.(*multiError); ok {
  371. nonNilErrs = append(nonNilErrs, nested.errors...)
  372. } else {
  373. nonNilErrs = append(nonNilErrs, err)
  374. }
  375. }
  376. return &multiError{errors: nonNilErrs}
  377. }
  378. // Combine combines the passed errors into a single error.
  379. //
  380. // If zero arguments were passed or if all items are nil, a nil error is
  381. // returned.
  382. //
  383. // Combine(nil, nil) // == nil
  384. //
  385. // If only a single error was passed, it is returned as-is.
  386. //
  387. // Combine(err) // == err
  388. //
  389. // Combine skips over nil arguments so this function may be used to combine
  390. // together errors from operations that fail independently of each other.
  391. //
  392. // multierr.Combine(
  393. // reader.Close(),
  394. // writer.Close(),
  395. // pipe.Close(),
  396. // )
  397. //
  398. // If any of the passed errors is a multierr error, it will be flattened along
  399. // with the other errors.
  400. //
  401. // multierr.Combine(multierr.Combine(err1, err2), err3)
  402. // // is the same as
  403. // multierr.Combine(err1, err2, err3)
  404. //
  405. // The returned error formats into a readable multi-line error message if
  406. // formatted with %+v.
  407. //
  408. // fmt.Sprintf("%+v", multierr.Combine(err1, err2))
  409. func Combine(errors ...error) error {
  410. return fromSlice(errors)
  411. }
  412. // Append appends the given errors together. Either value may be nil.
  413. //
  414. // This function is a specialization of Combine for the common case where
  415. // there are only two errors.
  416. //
  417. // err = multierr.Append(reader.Close(), writer.Close())
  418. //
  419. // The following pattern may also be used to record failure of deferred
  420. // operations without losing information about the original error.
  421. //
  422. // func doSomething(..) (err error) {
  423. // f := acquireResource()
  424. // defer func() {
  425. // err = multierr.Append(err, f.Close())
  426. // }()
  427. //
  428. // Note that the variable MUST be a named return to append an error to it from
  429. // the defer statement. See also [AppendInvoke].
  430. func Append(left error, right error) error {
  431. switch {
  432. case left == nil:
  433. return right
  434. case right == nil:
  435. return left
  436. }
  437. if _, ok := right.(*multiError); !ok {
  438. if l, ok := left.(*multiError); ok && !l.copyNeeded.Swap(true) {
  439. // Common case where the error on the left is constantly being
  440. // appended to.
  441. errs := append(l.errors, right)
  442. return &multiError{errors: errs}
  443. } else if !ok {
  444. // Both errors are single errors.
  445. return &multiError{errors: []error{left, right}}
  446. }
  447. }
  448. // Either right or both, left and right, are multiErrors. Rely on usual
  449. // expensive logic.
  450. errors := [2]error{left, right}
  451. return fromSlice(errors[0:])
  452. }
  453. // AppendInto appends an error into the destination of an error pointer and
  454. // returns whether the error being appended was non-nil.
  455. //
  456. // var err error
  457. // multierr.AppendInto(&err, r.Close())
  458. // multierr.AppendInto(&err, w.Close())
  459. //
  460. // The above is equivalent to,
  461. //
  462. // err := multierr.Append(r.Close(), w.Close())
  463. //
  464. // As AppendInto reports whether the provided error was non-nil, it may be
  465. // used to build a multierr error in a loop more ergonomically. For example:
  466. //
  467. // var err error
  468. // for line := range lines {
  469. // var item Item
  470. // if multierr.AppendInto(&err, parse(line, &item)) {
  471. // continue
  472. // }
  473. // items = append(items, item)
  474. // }
  475. //
  476. // Compare this with a version that relies solely on Append:
  477. //
  478. // var err error
  479. // for line := range lines {
  480. // var item Item
  481. // if parseErr := parse(line, &item); parseErr != nil {
  482. // err = multierr.Append(err, parseErr)
  483. // continue
  484. // }
  485. // items = append(items, item)
  486. // }
  487. func AppendInto(into *error, err error) (errored bool) {
  488. if into == nil {
  489. // We panic if 'into' is nil. This is not documented above
  490. // because suggesting that the pointer must be non-nil may
  491. // confuse users into thinking that the error that it points
  492. // to must be non-nil.
  493. panic("misuse of multierr.AppendInto: into pointer must not be nil")
  494. }
  495. if err == nil {
  496. return false
  497. }
  498. *into = Append(*into, err)
  499. return true
  500. }
  501. // Invoker is an operation that may fail with an error. Use it with
  502. // AppendInvoke to append the result of calling the function into an error.
  503. // This allows you to conveniently defer capture of failing operations.
  504. //
  505. // See also, [Close] and [Invoke].
  506. type Invoker interface {
  507. Invoke() error
  508. }
  509. // Invoke wraps a function which may fail with an error to match the Invoker
  510. // interface. Use it to supply functions matching this signature to
  511. // AppendInvoke.
  512. //
  513. // For example,
  514. //
  515. // func processReader(r io.Reader) (err error) {
  516. // scanner := bufio.NewScanner(r)
  517. // defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
  518. // for scanner.Scan() {
  519. // // ...
  520. // }
  521. // // ...
  522. // }
  523. //
  524. // In this example, the following line will construct the Invoker right away,
  525. // but defer the invocation of scanner.Err() until the function returns.
  526. //
  527. // defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
  528. //
  529. // Note that the error you're appending to from the defer statement MUST be a
  530. // named return.
  531. type Invoke func() error
  532. // Invoke calls the supplied function and returns its result.
  533. func (i Invoke) Invoke() error { return i() }
  534. // Close builds an Invoker that closes the provided io.Closer. Use it with
  535. // AppendInvoke to close io.Closers and append their results into an error.
  536. //
  537. // For example,
  538. //
  539. // func processFile(path string) (err error) {
  540. // f, err := os.Open(path)
  541. // if err != nil {
  542. // return err
  543. // }
  544. // defer multierr.AppendInvoke(&err, multierr.Close(f))
  545. // return processReader(f)
  546. // }
  547. //
  548. // In this example, multierr.Close will construct the Invoker right away, but
  549. // defer the invocation of f.Close until the function returns.
  550. //
  551. // defer multierr.AppendInvoke(&err, multierr.Close(f))
  552. //
  553. // Note that the error you're appending to from the defer statement MUST be a
  554. // named return.
  555. func Close(closer io.Closer) Invoker {
  556. return Invoke(closer.Close)
  557. }
  558. // AppendInvoke appends the result of calling the given Invoker into the
  559. // provided error pointer. Use it with named returns to safely defer
  560. // invocation of fallible operations until a function returns, and capture the
  561. // resulting errors.
  562. //
  563. // func doSomething(...) (err error) {
  564. // // ...
  565. // f, err := openFile(..)
  566. // if err != nil {
  567. // return err
  568. // }
  569. //
  570. // // multierr will call f.Close() when this function returns and
  571. // // if the operation fails, its append its error into the
  572. // // returned error.
  573. // defer multierr.AppendInvoke(&err, multierr.Close(f))
  574. //
  575. // scanner := bufio.NewScanner(f)
  576. // // Similarly, this scheduled scanner.Err to be called and
  577. // // inspected when the function returns and append its error
  578. // // into the returned error.
  579. // defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
  580. //
  581. // // ...
  582. // }
  583. //
  584. // NOTE: If used with a defer, the error variable MUST be a named return.
  585. //
  586. // Without defer, AppendInvoke behaves exactly like AppendInto.
  587. //
  588. // err := // ...
  589. // multierr.AppendInvoke(&err, mutltierr.Invoke(foo))
  590. //
  591. // // ...is roughly equivalent to...
  592. //
  593. // err := // ...
  594. // multierr.AppendInto(&err, foo())
  595. //
  596. // The advantage of the indirection introduced by Invoker is to make it easy
  597. // to defer the invocation of a function. Without this indirection, the
  598. // invoked function will be evaluated at the time of the defer block rather
  599. // than when the function returns.
  600. //
  601. // // BAD: This is likely not what the caller intended. This will evaluate
  602. // // foo() right away and append its result into the error when the
  603. // // function returns.
  604. // defer multierr.AppendInto(&err, foo())
  605. //
  606. // // GOOD: This will defer invocation of foo unutil the function returns.
  607. // defer multierr.AppendInvoke(&err, multierr.Invoke(foo))
  608. //
  609. // multierr provides a few Invoker implementations out of the box for
  610. // convenience. See [Invoker] for more information.
  611. func AppendInvoke(into *error, invoker Invoker) {
  612. AppendInto(into, invoker.Invoke())
  613. }
  614. // AppendFunc is a shorthand for [AppendInvoke].
  615. // It allows using function or method value directly
  616. // without having to wrap it into an [Invoker] interface.
  617. //
  618. // func doSomething(...) (err error) {
  619. // w, err := startWorker(...)
  620. // if err != nil {
  621. // return err
  622. // }
  623. //
  624. // // multierr will call w.Stop() when this function returns and
  625. // // if the operation fails, it appends its error into the
  626. // // returned error.
  627. // defer multierr.AppendFunc(&err, w.Stop)
  628. // }
  629. func AppendFunc(into *error, fn func() error) {
  630. AppendInvoke(into, Invoke(fn))
  631. }