Using Go to build a REST service on top of mongoDB

3 minute read

I’ve been following go (go-lang) for a while now and finally had some time to experiment with it a bit more. In this post we’ll create a simple HTTP server that uses mongoDB as a backend and provides a very basic REST API.

In the rest of this article I assume you’ve got a go environment setup and working. If not, look at the go-lang website for instructions (https://golang.org/doc/install). Before we get started we need to get the mongo drivers for go. In a console just type the following:

go get gopkg.in/mgo.v2

This will install the necessary libraries so we can access mongoDB from our go code.

We also need some data to experiment with. We’ll use the same setup as we did in my previous article (http://www.smartjava.org/content/building-rest-service-scala-akka-http-akka-streams-and-reactive-mongo).

Loading data into MongoDB

We use some stock related information which you can download from here (http://jsonstudio.com/wp-content/uploads/2014/02/stocks.zip). You can easily do this by executing the following steps:

First get the data:

    wget http://jsonstudio.com/wp-content/uploads/2014/02/stocks.zip

Start mongodb in a different terminal

    mongod --dbpath ./data/

And finally use mongoimport to import the data

     unzip -c stocks.zip | mongoimport --db akka --collection stocks --jsonArray

And as a quick check run a query to see if everything works:

jos@Joss-MacBook-Pro.local:~$ mongo akka      
MongoDB shell version: 2.4.8
connecting to: akka
> db.stocks.findOne({},{Company: 1, Country: 1, Ticker:1 } )
{
        "_id" : ObjectId("52853800bb1177ca391c17ff"),
        "Ticker" : "A",
        "Country" : "USA",
        "Company" : "Agilent Technologies Inc."
}
> 

At this point we have our test data and can start creating our go based HTTP server. You can find the complete code in a Gist here: https://gist.github.com/josdirksen/071f26a736eca26d7ea4

In the following section we’ll look at various parts of this Gist to explain how to setup a go based HTTP server.

The main function

When you run a go application, go will look for the main function. For our server this main function looks like this:

This will configure a server to run on port 8000, and any request that comes in will be handled by the NewHandler() instance we create in line 64. We start the server by calling the server.listenAndServe() function.

Now lets look at our handler that will respond to requests.

The myHandler struct

Lets first look at what this handler looks like:

Lets split this up and look at the various parts. The first thing we do is define a constructor:

When we call this constructor this will instantiate a myHandler type and call the defineMappings() function. After that it will return the instance we created.

How does the type look we instantiate:

As you can we define a struct with a mux variable as a map. This map will contain our mapping between a request path and a function that can handle the request.

In the constructor we also called the defineMappings function. This funtion, which is defined on out myHandler struct, looks like this:

In this (badly named) function we define the mapping between incoming requests and a specific function that handles the request. And in this function we also create a session to mongoDB using the mgo.Dial function. As you can see we define the requestHandlers in two different ways. The handler for “/hello” directly points to a function, an the handler for the “/get” path, points to a wrap function which is also defined on the myHandler struct:

This is a function, which returns a function. The reason we do this, is that we also want to pass our mongo session into the request handler. So we create a custom wrapper function, which has the correct signature, and just pass each call to a function where we also provide the mongo session. (Note that we also could have changed the ServeHTTP implementation we explain below)

Finally we define the ServeHTTP function on our struct. This function is called whenever we receive a request:

In this function we check whether we have a match in our mux variable. If we do, we call the configured handle function. If not, we just respond with a simple String.

The request handle functions

Lets start with the handle function which handles the “/hello” path:

Couldn’t be easier. We simply write a specific string as HTTP response. The “/get” path is more interesting:

What we do here is that we make use of the channel functionality of go to run three queries at the same time. We get the ticker information for AAPL, GOOG and MSFT and return a result to the specific channel. When we receive a response on one of the channels we return that response. So each time we call this service we either get the results for AAPL, for GOOG or for MSFT.

With that we conclude this first step into go-lang :)

Updated: