pram
pram

Reputation: 642

Handling errors for debugging in Go

I'm wondering if there are any better methods for handling errors in an application for debugging. I want to have a flag like 'debug' set, and it will display the real errors returned (like for example from sql) from the functions. If it isn't set I want it to return a generic message.

I made something that works this way here: http://play.golang.org/p/YDeqVvRSMd

The general idea is I pass the real error and my stock error into a function and it checks to see if debug is set:

func ErrorMsg(debug, error_type error) map[string]interface{} {

    var msg error

    if Debug {
        msg = debug
    } else {
        msg = error_type
    }

    err := map[string]interface{}{"error_message": msg}

    return err
}

However this kinda seems like an ugly solution. Is there a better way to accomplish this?

Also I want to return a JSON response, which is why it's a map.

Upvotes: 0

Views: 274

Answers (2)

jmaloney
jmaloney

Reputation: 12280

You could create a DebugError type that contains both your display and debug error, this type would also implement the Error interface. Then you could use a helper function to print the error.

package main

import (
    "errors"
    "fmt"
)

var ErrInternal = errors.New("Internal Server Error")

type DebugError struct {
    Display error
    Debug   error
}

// Error implements the error interface
// Uses the Display error
func (err DebugError) Error() string {
    return err.Display.Error()
}

func main() {
    err := someSqlCall()
    if err != nil {
        // debug error
        fmt.Println(getError(err, true))
        // display error
        fmt.Println(getError(err, false))
    }
}

// mock sql function
func someSqlCall() error {
    return DebugError{
        Display: ErrInternal,
        Debug:   errors.New("Real sql error goes here"),
    }
}

// getError is a helper function that returns a debug or display error
func getError(err error, debug bool) error {
    debugErr, ok := err.(DebugError)
    if !ok {
        // not a debug error
        return err
    }

    if debug {
        return debugErr.Debug
    }

    return debugErr.Display
}

Go play.

P.S. Personally I keep it simple and log all of my errors.

Upvotes: 2

OneOfOne
OneOfOne

Reputation: 99215

Go is a very verbose language, there isn't much you can do to clean that code up, here's a tiny bit shorter version:

func ErrorMsg(debug, error_type error) map[string]interface{} {
    msg := error_type
    if Debug {
        msg = debug
    }
    return map[string]interface{}{"error_message": msg}
}

Or you can drop the map all together and return the error directly and set json tags on the error struct:

type RequestError struct {
    ErrorString string `json:"error_message"`
}
func ErrorMsg(debug, error_type error) (err error) {
    err = error_type
    if Debug {
        err = debug
    }
    return
}

playground

Upvotes: 2

Related Questions