You can use example below to create custom errors in Go applications. They are useful if the application behaviour depends on error types. One makes use of variables as built-in errors and the other implements built-in error interface.


Example


package shoe

import "errors"

// ------------------------------------------------

var ErrTooSmall = errors.New("that shoe is too small")
var ErrTooBig = errors.New("that shoe is too big")

// ------------------------------------------------

type NarrowError struct {
Message string
}

func NewNarrowError(m string) NarrowError {
return NarrowError{Message:m}
}

func (n NarrowError) Error() string {
return n.Message
}

// ------------------------------------------------

type SmallError struct {
Message string
}

func NewSmallError(m string) SmallError {
return SmallError{Message:m}
}

func (s SmallError) Error() string {
return s.Message
}

package main

import (
"fmt"
"log"
"os"

"cmd/shoe"
)

func main() {
// Change these values to see the result.
var (
width = 5
length = 10
)

err := checkShoeSize("inanzzz", width, length)
if err != nil {
log.Println(err.Error())

switch err.(type) {
case shoe.NarrowError:
fmt.Println(fmt.Sprintf("Go and get wider shoe then %d width.", width))
case shoe.SmallError:
fmt.Println(fmt.Sprintf("Go and get bigger shoe then %d length.", length))
default:
if err == shoe.ErrTooSmall {
fmt.Println(
fmt.Sprintf("Go and get bigger shoe then %d width and %d length.", width, length),
)
}
if err == shoe.ErrTooBig {
fmt.Println(
fmt.Sprintf("Go and get smaller shoe then %d width and %d length.", width, length),
)
}
}

os.Exit(0)
}

fmt.Println(fmt.Sprintf("Good fit shoe, %d width %d length", width, length))
}

func checkShoeSize(customer string, width, length int) error {
if width < 5 && length < 10 {
return shoe.ErrTooSmall
}

if width > 20 && length > 30 {
return shoe.ErrTooBig
}

if width < 10 {
return shoe.NewNarrowError(
fmt.Sprintf("Customer %s's shoe is too narrow, %d width.", customer, width),
)
}

if length < 20 {
return shoe.NewSmallError(
fmt.Sprintf("Customer %s's shoe is too small, %d length.", customer, length),
)
}

return nil
}

Test


$ go run -race main.go 
2020/02/06 20:19:28 Customer inanzzz's shoe is too narrow, 5 width.
Go and get wider shoe then 5 width.

Classic way


var ErrClosed = &Error{code: 100, message: "connection is not open"}
var ErrMemory = &Error{code: 200, message: "out of memory"}

type Error struct {
code int
message string
}

func (e Error) Code() int {
return e.code
}

func (e Error) Error() string {
return e.message
}

Then check error using errors.Is(err, ErrMemory).