Go with interfaces + private opaque types

rather than public types that wrap slices
This commit is contained in:
Dan Buch
2016-05-25 12:05:14 -04:00
parent cd1e8c3452
commit 3d75e9e711
11 changed files with 187 additions and 141 deletions

View File

@@ -15,25 +15,39 @@ var OsExiter = os.Exit
var ErrWriter io.Writer = os.Stderr
// MultiError is an error that wraps multiple errors.
type MultiError struct {
errors []error
type MultiError interface {
error
// Errors returns a copy of the errors slice
Errors() []error
}
// NewMultiError creates a new MultiError. Pass in one or more errors.
func NewMultiError(err ...error) MultiError {
return MultiError{errors: err}
func newMultiError(err ...error) MultiError {
ret := multiError(err)
return &ret
}
// Error implents the error interface.
func (m MultiError) Error() string {
errs := make([]string, len(m.errors))
for i, err := range m.errors {
type multiError []error
// Error implements the error interface.
func (m *multiError) Error() string {
errs := make([]string, len(*m))
for i, err := range *m {
errs[i] = err.Error()
}
return strings.Join(errs, "\n")
}
// Errors returns a copy of the errors slice
func (m *multiError) Errors() []error {
errs := make([]error, len(*m))
for _, err := range *m {
errs = append(errs, err)
}
return errs
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type ExitCoder interface {
@@ -41,29 +55,25 @@ type ExitCoder interface {
ExitCode() int
}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type ExitError struct {
type exitError struct {
exitCode int
message string
}
// NewExitError makes a new *ExitError
func NewExitError(message string, exitCode int) *ExitError {
return &ExitError{
// Exit wraps a message and exit code into an ExitCoder suitable for handling by
// HandleExitCoder
func Exit(message string, exitCode int) ExitCoder {
return &exitError{
exitCode: exitCode,
message: message,
}
}
// Error returns the string message, fulfilling the interface required by
// `error`
func (ee *ExitError) Error() string {
func (ee *exitError) Error() string {
return ee.message
}
// ExitCode returns the exit code, fulfilling the interface required by
// `ExitCoder`
func (ee *ExitError) ExitCode() int {
func (ee *exitError) ExitCode() int {
return ee.exitCode
}
@@ -85,7 +95,7 @@ func HandleExitCoder(err error) {
}
if multiErr, ok := err.(MultiError); ok {
for _, merr := range multiErr.errors {
for _, merr := range multiErr.Errors() {
HandleExitCoder(merr)
}
}