Skip to content

Go error implementation for applications with error code, message, nested errors, attached data, ...

License

Notifications You must be signed in to change notification settings

app-kit/go-apperror

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-apperror

Go error implementation for applications that supports nested errors.

Go s error implementation is rather simplistic, and leaves a lot to be desired for applications that require more complex errors.

This package provides an Error interface and and an apperror.Err implementation to provide rich errors, both internally and to a possibly public frontend.

The Error interface of course implements the go Error interface, so you can always use use app errors as plain errors when required.

Errors can contain the following data:

  • Code: a string code that uniquely identifies the error.
  • Status: an integer value to identify the type of error (for example an http status code, or a unique error number).
  • Message: an explicative message intended for humans.
  • Data: arbitrary data related to the error.
  • Errors: nested errors
  • Public: specifies whether the error may be presented publically (for example to an api user or website)

Usage

import(
	"fmt"
	"github.com/theduke/go-apperror"
)

// Creating a new error.
func createString() (string, apperror.Error) {
	// Return an error with 'code' "my_application_error", 'status' 22 and a message.
	return "", apperror.New("my_application_error", 22, "Could not create string")
}

// Checking for errors.

func CreateString() string {
	s, err := createString()

	// Check if the error has a specific code.
	if apperror.IsCode("my_application_error") {
		fmt.Printf("XX error occured")
	} 

	// Check for error status.
	if apperror.IsStatus(33) {
		fmt.Printf("Error status 33")
  }

  return s
}

// Wrapping nested errors.

func dbQuery(q string) ([]string, apperror.Error) {
	result, err := db.Query(q)
	if err != nil {
		// Wrap the database error with a generic PUBLIC error.
		// The "true" argument makes the error public, which allows the error to be presented
		// to users.
		publicErr := apperror.Wrap(err, "db_query_error", "Database query failed", true)

		// The original error can be accessed with err.GetErrors()
		for _, err := range  publicErr.GetErrors() {
			fmt.Printf("Nested error: %v\n", err)
		}

		// Additional nested errors can be added.
		publicErr.AddError(errors.New("other_error"))
	}
	return result, nil
}

// Working with errors.

func handleError(err apperror.Error) {
	code := err.GetCode()
	status := err.GetStatus()
	msg := err.GetMessage()
	nestedErrors := err.GetErrors()
	data := err.GetData()

	isPublic := err.IsPublic()

	// Handle specific errors...
}

Reference

apperror.New()

Create a new error.

// For apperror.New(), only the  code argument is  required.
// All additional arguments can be in any order.

err := apperror.New(code string, [status int,] [message string,] [data interface{}, ] [isPublic bool,] [nestedErrors []error])

apperror.Wrap()

Wrap an error.

// For apperror.Wrap(), the original error and the code argument are required.
// All additional arguments can be in any order.

 apperror.Wrap(originalError error, code string, [status int,] [message string,] [data interface{}, ] [isPublic bool,]) apperror.Error

apperror.IsCode

Check if an error has a code.

apperror.IsCode(err error, code string) bool

apperror.IsStatus

Check if an error has a status.

apperror.IsStatus(err error, status int) bool

Manually creating errors.

You can also manually create the error.

err := &apperror.Err{
	Code: "code",
	Status: 111,
	Message: "msg",
	Data: []string{"1", "2"},
	Errors: []error{errors.New("xxx")},
	Public: true,
}
return err

Marshal

Err implements the json Marshal interface to provide more advanced marshalling for public errors:

The marshaled error will not include nested errors.

If marshaling a non-public error, all data will be stripped and the error will just contain the Code "app_error" and a generic error message.

Tipps

  • Always use the apperror.Error interface in function signatures, not the implementation apperror.Err. This allows you to use different implementations if appropriate.
  • Set errors intended for end users to Public, and check to only show public errors.

About

Go error implementation for applications with error code, message, nested errors, attached data, ...

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages