0

Asking a Golang question as someone coming from the Ruby & JS worlds, so bear with me if this is a rather simple Go question :)

Working with the Gorilla toolkit on an API, and I'm not sure if my thinking is totally correct on something. I've been reading through the thoroughly-excellent The Go Programming Language, but am decidedly not expert at Go yet. When sending back a JSON response, I've been doing something like the below to send back an object like this:

{ "healthy": true, "version": "0.0.1" }

But I'm not sure if it's a best practice or idiomatic to go to be creating one-off structures like appHealth or if I'm thinking too-much like I would in JS, where I'd just throw up an object literal and return the JSON-ified version of that to the client. Teach me, wise gophers.

Thank you!

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "os"

    "github.com/gorilla/mux"
)

type appHealth struct {
    Healthy bool
    Version string
}

func health(w http.ResponseWriter, r *http.Request) {
    health := appHealth{true, "0.0.1"}
    json.NewEncoder(w).Encode(health)
}

func main() {
    port := os.Getenv("PORT")
    router := mux.NewRouter().StrictSlash(false)
    router.HandleFunc("/health", health)
    log.Fatal(http.ListenAndServe(":"+port, router))
}
5
  • There's nothing innately wrong with doing that: you're going to re-use it across requests, you can extend it, the structure is clear, etc. If anything, you should make sure to handle the error from Encode. Commented Apr 16, 2016 at 23:22
  • Cool! Just felt weird, but it seems like being explicit like that is more characteristic of a strongly-typed language, so I'm sure I'll get used to it. What would be the best way to handle the encode error? panic? Commented Apr 16, 2016 at 23:25
  • Only panic in exceptional cases. Just catch the error and log it (because it's too late to do anything once you've started writing to the response), or write to a temporary buffer (bytes.Buffer) first, and if there are no errors, io.Copy(buf, w) to write it out. Probably overkill for a simple data structure like this, but useful when dealing with more complex data (e.g. large structures from a DB -> JSON). Commented Apr 16, 2016 at 23:39
  • Technically, that version parameter in that json json will not parse to anything (not a double cause it's invalid, not a string because it isn't in quotes, etc). you'll want to put it into quotes before send it across the wire. there are custom marshallers you can implement, but easier just to put it in quotes for proper json. Commented Apr 16, 2016 at 23:59
  • @eduncan911 thanks for pointing that out, that was an oversight on my part :) updated question Commented Apr 17, 2016 at 0:01

1 Answer 1

1

Looks pretty good. Don't be afraid to make types for that will add to the meaning.

type Version string  

You can then have logic for what a version looks like that will be tied to the type

Or you might want to check out juju's version package.

If you really have a struct that is a one off, you can do an anonymous struct with a literal.

health := struct{ 
    Health bool
    Version string
}{
    true,
    "1.2.3",
}
Sign up to request clarification or add additional context in comments.

1 Comment

It hadn't occurred to me that struct could be lexically lexically scoped using blocks +1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.