I had been playing around with Go for a few years. The last two years I had been doing the adventofcode.com with Go after running into some insanely long run times doing some the exercises with JS and PHP. Go would run some of these super complex algorithms (like path finding and simulations) in no time at all. I kept saying I wanted to eventually start building some web applications with Go but never really had a chance.
When we started to discuss the idea of rebuilding our web app someone threw out the idea of building the API with Go and using Vue.js for the frontend. I had played with Vue in the past and really liked it. It was very similar to React, however for a few small reasons I just liked Vue more. My only fear was that no one on the team had any real experience with Go. I had the most experience and I hadn’t done hardly any web stuff with Go. But we decided to make the jump and started to move ahead with the plan.
First I looked to see if there were any popular frameworks or packages people used when creating RESTful APIs in Go. There are a few Go frameworks but most of them are pretty early in their development life cycle. After reading quite a few articles almost everyone recommended building without one of these frameworks. So the decision was made to not use a framework for our API.
My first step was to learn how Go’s http package worked. When the creators of Go created the language they wanted to include http as part of the language, it wasn’t an after thought like a lot of other programming languages. So Go by default has an http server built in with routing and most of your basic functionality. After playing around with this for a little while I realized their core router was a little simplistic for what I wanted to do, so I did some research and found gorilla/mux a Go router that added a decent amount of functionality like sub routers, prefixes, middleware, etc… A lot of people seemed to be using this package and I didn’t want to recreate the wheel so I decided we would use it for routing.
This brought up a new issue though, package/dependency management. With Node.js we have npm/yarn, with PHP we have composer, with Python we have pip, etc… So what options are there for Go? Unfortunately this is one of Go’s weakest points right now. There really isn’t a great option. There is
go get however that just installs packages locally, so if another develop was working on the code they wouldn’t know you added dependency to the project, there is no
composer.json or any other type of file like that.
vgo is super early in development. So really the only option that would work for us was
dep has been around for a while and while not great it gives you a
Gopkg.toml and a
Gopkg.lock so you can keep track of what dependencies you have added and version numbers.
So now that I had this all figured out I started to actually write some endpoints. However, things quickly started to get unorganized, which I hate. One of my favorite things about frameworks is they give an organization structure for where code should be. It makes it that much easier for other developers to find code and for you to find other people’s code. I found a github repo that had a pretty code project structure that I liked so I decided to mimic theirs.
After writing some mock endpoints now came the issue of actually connecting to a database and storing/retrieving data. When I used PHP I used Laravel and loved their ORM and the database migration features. When we used Node we used sequelize which offered some of that similar functionality. So it was time to find out if there was an ORM with migrations for Go. I pretty quickly realized the answer to that question was “not really”. Yes there were some ORMs and yes some of them had some migration type features, but none of them really had the features I was looking for. So first I decided to pick out an ORM and decided on Gorm. Gorm gives some low level migration options but it doesn’t give you versioning and options like
down commands. So then I looked for other migration packages and found Goose. Goose gives you the ability to create migration files, and go forward and backwards. So by using these two packages we got the basic functionality we were looking for, we could now programmatically modify our database structure and also use an ORM to provide some abstraction from the database directly.
After we had all this in place the rest of the code was pretty easy to write. So the learning curve was a little steep at the beginning but once we got over that hump we cranked out the rest of the API pretty quickly. We were then able to write our frontend in Vue.js without any problems at all. The combination of Go on the backend and Vue on the frontend is awesome. The user experience is amazing, everything loads insanely fast and even though we have code that displays loaders while data is being retrieved via ajax I personally have never even seen them show up because the api is so fast. Not only is the API fast the footprint on the server is so low that I thought our reporting was incorrect. When we first loaded it onto Heroku it showed that the Memory Usage was 8MB. I thought for sure something went wrong with our deployment, but I tried to hit the api and sure enough it responded. So I decided to do a decent load test on it, I think the highest I saw the Memory Usage get was around 20 MB. I also ran an apache benchmark test in my own local development environment. Even hitting an endpoint that hit the database I could pretty easily get round 7,000 requests per second running
ab -t 10 -c 100 http://127.0.0.1:8000/api/users/1.