DEV Community

Cover image for errors handling in GO!
Abdelhak Akermi
Abdelhak Akermi

Posted on

errors handling in GO!

Today many programmers find it difficult to handle errors resulting from code bugs or by notification by the user, the developers are responsible for these errors for not noticing, in this series I will explain methods of handling errors in Golang .Go errors are implemented in the Error interface and must be handled in every layer of code. Go errors don't work like exceptions, and unhandled errors can cause massive problems. You should seek to deal with errors and consider them when they occur.

The Error interface

The error type is a simple interface type :


type Error interface{
  Error() string
}

to create error value in package level that you can check ,you can use
error.New() implemented in errorspackage

// ErrorNotValidURL is a description of a not valid URL
var ErrorNotValidURL = errors.New("given text is not url")

// we check errors value

if err == urlextractor.ErrorNotValidURL {
  fmt.Println("not a valid url ")
 }

to make an error type, you declare new struct with error's name

// NotValidURLError is a description of a malformed URL
type NotValidURLError struct {
 error
}
// We check the type of the error

 switch _, err := urlextractor.IsURL("not URL !"); err.(type) {
 case nil:
  fmt.Println("No Error returned")
 case urlextractor.NotValidURLError:
  fmt.Println("Type1 Error: ", err)

 }

a flexible way to implement custom error is as a struct that will implement the error() interface that you can put extra functions
to add more pieces of information on the error type


// NotValidURLError is a struct that will implement
// the Error() interface
type NotValidURLError struct {
 Source string
}

func (c NotValidURLError) Error() string {
 return fmt.Sprintf("%s is not valid URL", c.Source)
}

the only requirement to use Error() interface only returns a valid string, you can combine this with a structure to provide a consistent error handling throughout

Wrapping errors

when you implement a new library that contains complex manipulation you need to ensure to keep traces of context in errors by prefixing them or printing the full stack trace,to annotate an error in such manner, the github.com/pkg/errors package has the following function

// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error

the wrap function takes an error, and a message and produces a new error

// URLExtractorError demonstrates error wrapping and
// annotating an error
func URLExtractorError(e error) error {
 return errors.Wrap(e, "An error occurred in URLExtractor")
}
func IsURL(url string) (bool, error) {
 re := regexp.MustCompile(`^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$`)
 result := re.Find([]byte(url))
 if len(result) == 0 {
  return false, URLExtractorError(NotValidURLError{errors.New("malformed URL :" + url)})
 }

 return true, nil

}

We’ll use this function from the main

func main() {
 _, err := urlextractor.IsURL("not URL !")

 if err != nil {
  fmt.Println(err)
 }
}

when IsURL fail, we get the annotated error

An error occurred in URLExtractor: malformed URL: not URL!

to inspect the stack trace we can do more by replacing fmt.Println(err) with fmt.Printf("%+v\n", err)

go-err/urlextractor.URLExtractorError
        /home/abdelhak/LP/go-err/urlextractor/urlextract.go:20
go-err/urlextractor.IsURL
        /home/abdelhak/LP/go-err/urlextractor/urlextract.go:38

Discussion (0)