Why Go?

Because I like it, that’s why! And it’s pragmatic but one-way-to-do-it spirit fits my personality. After spending months with Java for school it is an absolute joy to work with. I’ll touch on some of the more interesting things I encountered while working on the project. The details are in the source of course, which I worked hard to keep readable and annotated.

Heroku

I had not used Heroku previously, so I spent quite a bit of time just getting started with it. Fortuanely, while not as easy to work with as surge.sh I didn’t find it too difficult to get going with. But there were a few snags. Go tooling aside, it wasn’t quite as simple as pointing heroku at a binary, but in the end, it wasn’t much different than that either.

There were a few different ways to signal to Heroku that the deployed app is written in Go, but I found the simplest, especially since I didn’t plan on using anything other than the standard library, was to use gb. The instructions for doing so, summarized:

  • create a src directory at your project root
  • write some .go files inside src
  • at least one of which should compile into a binary, let’s call it foo
  • create a file called Procfile in the project root that says: web: foo

And that’s it!

Serving Millions

Serving http is dead simple with Go, here is the entirety of a working webserver function:

func main() {
	port := os.Getenv("PORT")
	
	http.HandleFunc("/", timestamp) 
	http.ListenAndServe(":"+port, nil)
}

Grabbing the port from the environment was another snag I ran into. You won’t know what port your particular app is being served from, so it needs to be grabbed dynamically. timestamp in the above code is the name of a function that does the work of reading requests and writing responses. Originally all my logic was in this function, but I later refactored it away so that timestamp is only concerned with http and any business logic is handled elsewhere.

Jason and the Argonauts

Go also has some pleasant tools to work with JSON. I defined a concrete type to hold the data:

type TimeResponse struct {
	Unix    *string `json:"unix"`
	Natural *string `json:"natural"`
}

Converting a value of this type to JSON notation can be performed with json.MarshalIndent(someResponseValue, "", " ") json.Marshal would do the same thing without the extra arguments and thus no pretty printing.

Time Flies When You’re Coding

Go has a bit of unique way to represent time formats (any string representation of a certain fixed date), but I took advantage of the relative ease of defining them to extend the user story beyond the requirements, allowing a great variety of date formats to be parsed correctly. https://timestamp-go.herokuapp.com/12/25/2017/ was particularly fun to get working. Great apologies to the rest of the world, but I choose the American way to parse that style of date.

Room for Improvement

How could this particular project be improved?

  • The instructions page is pure text, so even a little html and css would make it more pleasant to read.
  • More time formats!
  • Optional query string to request a certain format of natural date/time.

Gitter Done

A brief technical note, for myself as much as anything, since I’m holding the code for this in my overarching fcc repo, I used a git subtree to push just the relevant code to a branch. Heroku is configured to do automatic deployments from this branch. The incantation is:

git subtree push --prefix timestamp/go/ origin timestamp-go

This must be performed in the repo root, but will push only a specific directory timestamp/go/ to a specific branch timestamp-go.