Error handling in go - udaybhanu007/OVN-Poc GitHub Wiki
In this document you will find the following :
1. Introduction of error in go
1.2. Handling an error without a custom error handler
1.3. Creating a custom error handler
1. Introduction of error in go
1.2. Handling an error without a custom error handler
f, err := os.Open(filename)
if err != nil {
log.Printf("Body read error, %v", err)
w.WriteHeader(500) // Return 500 Internal Server Error.
return
}
The above code you can see without a custom error , is more verbose.
1.3. Creating a custom error handler
type error interface {
Error() string
}
type CustomError string
func (err CustomError) Error() string {
return string(err)
}
The main idea is to : Handle errors only once. Wrap them with additional information and return to caller function if necessary. It is more maintainable and scalable to handle (taking an action on error such as logging) them in a specific exit point/middleware.
In the demo code implementation i have created an implementation for error interface
type HTTPError struct {
Cause error `json:"-"`
Detail string `json:"detail"`
Status int `json:"-"`
}
func (e *HTTPError) Error() string {
if e.Cause == nil {
return e.Detail
}
return e.Detail + " : " + e.Cause.Error()
}
We can return errors directly from the handler function and process them in a single function outside.
type RootHandler func(http.ResponseWriter, *http.Request) error
http.Handle("/adduser", helpers.RootHandler(controllers.AddUser))
http.HandleFunc doesn’t understand the signature of this function (since we are returning error). Instead of using http.HandleFunc , we can use http.Handle which accepts any type that implements http.Handler interface. In other words, as long as you pass a type that has ServeHTTP method, the http.Handle function will be happy. All of the handler functions in our application will share the same error handling code, so we can define a new function type (rootHandler ) and write error handling part in ServeHTTP method. Now we can move error handling logic from AddUser to rootHandler.ServeHTTP function, which is:
-
Call actual handler function.
-
If there is no error returned from handler, just return from the function.
-
If there is an error: log the error and return an HTTP response to client
Please check the code for servehttp in the RootHandler.go file
Remember that we want to have two different main error types: Client Error for 4xx errors and Server Error (or Internal Error) for 5xx. We can declare interfaces based on the behavior we expect from these two types
But for simplicity, in the demo code i have combined them both to a single interface APIError . And in the real project in my opinion we should have the distinction.
Reference