How serious is "Naked Returns" in Go

Naked returns are the returns which return nothing. These issues appear in languages like C and as Go is highly inspired from that so it also hides this error under its cap. The point to note here is Go doesn't force the developer to add a return statement, when the error appears it doesn't print anything, error trace also turns out as a tough task.
Basic Scenario
Taking a basic handler with few error-prone function to delve into this. Here the operation2 doesn't even have a return, still Go will not cause any warning while running it. Compiler will go for a run easily. The function where there is a return, we are literally returning nothing. And the bugs this will cause, no one can even predict those. Handling naked returns is different at different cases, but mostly what you can do is either return a value or make the program exit completely. Here is a basic example of HTTP handler showcasing the issue.
func myHandler(w http.ResponseWriter, r *http.Request) {
res1, err := operation1()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
res2, err := operation2(res1)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
res3, err := operation3(res2)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write([]byte("Success: " + resThree))
}
Gin Scenario
Gin is here for sometime and has gained quite a bit popularity and yes, Gin also doesn't have any mechanism to tackle this issue.
// Example usng Gin framework
func (h *Handlers) pickAlbum(c gin.Context) {
id, ok := c.Params.Get("id")
if !ok {
c.Error(fmt.Errorf("Couldn't get the album: id is missing"))
return
}
al, err := h.db.findID(id)
if err != nil {
c.Error(fmt.Errorf("Got the album with an id of %s: %w", id, err))
// No return, but it will not complain
}
co, err := h.db.findCover(id)
if err != nil {
c.Error(fmt.Errorf("Got the cover for album with an id %s: %w", id, err))
return
}
c.JSON(http.StatusOK, gin.H{"album": al, "cover": co})
}
What can we do about it
Unlike other frameworks, Echo takes care of this. Sharing an example below
// Example using Echo framework
func (h *Handlers) pickAlbum(c echo.Context) error {
// Errors will be returning value here ⬆
id := c.QueryParam("id")
if id == "" {
return fmt.Errorf("Couldn't get the album: id is missing")
}
al, err := h.db.findID(id)
if err != nil {
return fmt.Errorf("Got the album with an id of %s: %w", id, err)
}
co, err := h.db.findCover(id)
if err != nil {
return fmt.Errorf("Got the cover for album with an id %s: %w", id, err)
}
return c.JSON(http.StatusOK, echo.Map{"album": al, "cover": co})
}
In this way Echo is forcing to handle the error by returning something, so from now onwards you can't ignore the error, you have to do something about it or else compiler will create noise about an unused variable. When you will return some value, Echo will show a suitable message with a HTTP status code using the response writer.
Apart from this any other way? Yes, we can do this without using the frameworks also, with pure Go. Little abstraction of the Writer will be required in this case
type myWriter struct {
w http.ResponseWriter
}
func (rw *myWriter ) printString(str string) error {
_, err := rw.w.Write([]byte(str))
return err
}
type myHandler func(w *myWriter , r *http.Request) error
// After abstraction here is an example of new Handler
func handler1(w *myWriter , r *http.Request) error {
res, err := operation1()
if err != nil {
return fmt.Errorf("someHandler: %w", err)
}
return w.printString(res)
}
// Piece of code to bridge the gape between existing HTTP package
func myHTTPHandler(fn myHandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
rw := MyResponseWriter{w: w}
err := fn(&rw, r)
if err != nil {
// Here we actually use the original writer's error reporting features
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
That's it for now. Thanks😊
Subscribe to my newsletter
Read articles from Asutosh Panda directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Asutosh Panda
Asutosh Panda
Curious about Outages, Distributed Systems, DevOps, Backend, SRE related stuffs.