Go Error handling on a REST API

Viewed 11990

I am very new to go and have deployed a small service with an API endpoint.

I have heard/read that go doesn't use try/catch so I am trying to figure out how I can "catch" any problems happening from my service call from my API and make sure that the resource server doesn't go down.

My code for my API looks like the following..

I have a routes.go file with the following

package main

import (
    "net/http"

    "github.com/gorilla/mux"
)

type Route struct {
    Name        string
    Method      string
    Pattern     string
    HandlerFunc http.HandlerFunc
}

type Routes []Route

func NewRouter() *mux.Router {
    router := mux.NewRouter().StrictSlash(true)
    for _, route := range routes {
        router.
            Methods(route.Method).
            Path(route.Pattern).
            Name(route.Name).
            Handler(route.HandlerFunc)
    }

    return router
}

var routes = Routes{
    Route{
        "CustomerLocationCreate",
        "POST",
        "/tracking/customer",
        CustomerLocationCreate,
    },
}

I have a handlers.go

package main

import (
    "encoding/json"
    "net/http"
    "io"
    "io/ioutil"
)

//curl -H "Content-Type: application/json" -d '{"userId":"1234"}' http://localhost:8181/tracking/customer
func CustomerLocationCreate(w http.ResponseWriter, r *http.Request) {
    var location CustomerLocation
    body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
    if err != nil {
        panic(err)
    }
    if err := r.Body.Close(); err != nil {
        panic(err)
    }
    if err := json.Unmarshal(body, &location); err != nil {
        w.Header().Set("Content-Type", "application/json; charset=UTF-8")
        w.WriteHeader(422) // unprocessable entity
        if err := json.NewEncoder(w).Encode(err); err != nil {
            panic(err)
        }
    }

    c := RepoCreateCustomerLocation(location)
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    w.WriteHeader(http.StatusCreated)
    if err := json.NewEncoder(w).Encode(c); err != nil {
        panic(err)
    }

    HandleCustomerLocationChange(c);
}

and I have a bus.go which has the HandleCustomerLocationChange(...) function.

func HandleCustomerLocationChange(custLoc CustomerLocation) {

    endpoint := og.Getenv("RABBIT_ENDPOINT")
    conn, err := amqp.Dial("amqp://guest:guest@" + endpoint)
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    topic := "locationChange"
    err = ch.ExchangeDeclare(
        topic,   // name
        "topic", // type
        true,    // durable
        false,   // auto-deleted
        false,   // internal
        false,   // no-wait
        nil,     // arguments
    )
    failOnError(err, "Failed to declare an exchange")

    // Create JSON from the instance data.
    body, _ := json.Marshal(custLoc)
    // Convert bytes to string.

    err = ch.Publish(
        topic, // exchange
        "",    // routing key
        false, // mandatory
        false, // immediate
        amqp.Publishing{
            ContentType: "text/plain",
            Body:        body,
        })
    failOnError(err, "Failed to publish a message")

    log.Printf(" [x] Sent %s", body)

}

My question is how should I modify both the HandleCustomerLocationChange(...) function and if necessaryCustomerLocationChange(..)` handler to handle errors properly so that if an error occurs, my entire API doesn't go down?

1 Answers
Related