 d77176912b
			
		
	
	
	d77176912b
	
	
	
		
			
			* Migrate to go modules * make vendor * Update mvdan.cc/xurls * make vendor * Update code.gitea.io/git * make fmt-check * Update github.com/go-sql-driver/mysql * make vendor
		
			
				
	
	
		
			77 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| Package warnings implements error handling with non-fatal errors (warnings).
 | |
| 
 | |
| import path:   "gopkg.in/warnings.v0"
 | |
| package docs:  https://godoc.org/gopkg.in/warnings.v0 
 | |
| issues:        https://github.com/go-warnings/warnings/issues
 | |
| pull requests: https://github.com/go-warnings/warnings/pulls
 | |
| 
 | |
| A recurring pattern in Go programming is the following:
 | |
| 
 | |
|  func myfunc(params) error {
 | |
|      if err := doSomething(...); err != nil {
 | |
|          return err
 | |
|      }
 | |
|      if err := doSomethingElse(...); err != nil {
 | |
|          return err
 | |
|      }
 | |
|      if ok := doAnotherThing(...); !ok {
 | |
|          return errors.New("my error")
 | |
|      }
 | |
|      ...
 | |
|      return nil
 | |
|  }
 | |
| 
 | |
| This pattern allows interrupting the flow on any received error. But what if
 | |
| there are errors that should be noted but still not fatal, for which the flow
 | |
| should not be interrupted? Implementing such logic at each if statement would
 | |
| make the code complex and the flow much harder to follow.
 | |
| 
 | |
| Package warnings provides the Collector type and a clean and simple pattern
 | |
| for achieving such logic. The Collector takes care of deciding when to break
 | |
| the flow and when to continue, collecting any non-fatal errors (warnings)
 | |
| along the way. The only requirement is that fatal and non-fatal errors can be
 | |
| distinguished programmatically; that is a function such as
 | |
| 
 | |
|  IsFatal(error) bool
 | |
| 
 | |
| must be implemented. The following is an example of what the above snippet
 | |
| could look like using the warnings package:
 | |
| 
 | |
|  import "gopkg.in/warnings.v0"
 | |
| 
 | |
|  func isFatal(err error) bool {
 | |
|      _, ok := err.(WarningType)
 | |
|      return !ok
 | |
|  }
 | |
| 
 | |
|  func myfunc(params) error {
 | |
|      c := warnings.NewCollector(isFatal)
 | |
|      c.FatalWithWarnings = true
 | |
|      if err := c.Collect(doSomething()); err != nil {
 | |
|          return err
 | |
|      }
 | |
|      if err := c.Collect(doSomethingElse(...)); err != nil {
 | |
|          return err
 | |
|      }
 | |
|      if ok := doAnotherThing(...); !ok {
 | |
|          if err := c.Collect(errors.New("my error")); err != nil {
 | |
|              return err
 | |
|          }
 | |
|      }
 | |
|      ...
 | |
|      return c.Done()
 | |
|  }
 | |
| 
 | |
| For an example of a non-trivial code base using this library, see
 | |
| gopkg.in/gcfg.v1
 | |
| 
 | |
| Rules for using warnings
 | |
| 
 | |
|  - ensure that warnings are programmatically distinguishable from fatal
 | |
|    errors (i.e. implement an isFatal function and any necessary error types)
 | |
|  - ensure that there is a single Collector instance for a call of each
 | |
|    exported function
 | |
|  - ensure that all errors (fatal or warning) are fed through Collect
 | |
|  - ensure that every time an error is returned, it is one returned by a
 | |
|    Collector (from Collect or Done)
 | |
|  - ensure that Collect is never called after Done
 |