Intro

Golang is pretty hot right now. Over the past few weeks, I've been exploring implementing some of the cloud infrastracture I'd previously built with node in go, partly for fun, partly because go is fast. This led me to believe that setting up a basic REST service would make for a great tutorial.

At the end, we will have a fully functioning REST service for serving basic CRUD on a user resource. Code for the final product can be found here.

This is the second in a series of high level tutorials on setting up a REST service using golang, focused on using public packages and defining a basic webserver.

Packages

Go allows for external packages to be accessed in your source via the import statement. These packages must be accessible somewhere in your GOPATH or GOROOT environment, depending on whether the packages come from a third party or the Go standard library, respectively. In the previous tutorial, you may have noticed that we imported the fmt package when we tested our setup. The fmt package is part of the standard library. You can find more standard library packages here.

Third party packages can be fetched via the go get command. There are a few special rules for fetching a remote package, described here, but for now we just need to understand the rules for packages publicly available on github. Put simply, any go package on github can fetched via the following.

$ go get github.com/USER/PROJECT

You'll notice there is no version information in the above command, which is another caveat of go. There are several solutions for this, such as using a makefile to set a temporary GOPATH within the application and checking dependencies into your source control. I've also grown fond of GoDep.

Router

Since we're trying to build out a webserver, let's find a router package. When searching for a go package to use, GoDoc is always a good place to start. There are many excellect candidates, but let's use the httprouter package. We first need to fetch the package with go get.

$ go get github.com/julienschmidt/httprouter

To get started, we first need to create a directory to host our application. If you followed along with the last tutorial, the following will get us started. Otherwise, setup a new directory somewhere in your GOPATH.

Here we are adding a new handler to respond to the "/test" route. Notice that the handler itself has a different signature than the standard http.HandlerFunc.

Also, we are able to respond to the request with fmt.Fprint. Strangely, if you look at the signature of fmt.Fprint, it shows the following.

func Fprint(w io.Writer, a ...interface{}) (n int, err error)

So how are we able to pass our instance of http.ResponseWriter to it as an io.Writer? Because io.Writer is an interface. Interfaces are implemented implicitly in go. In fact, http.ResponseWriter itself is an interface, which also satisfies the io.Writer interface.

And for the last interesting piece.

http.ListenAndServe("localhost:3000", r)

Here, as you can guess, we are firing up a webserver to listen on localhost:3000, using our router to handle requests. This is another instance where we can see the power of interfaces in go. http.ListenAndServe accepts an interface type http.Handler, which the author of httprouter provides as a convencience.

Let's go ahead and test our example server. First, fire it up.

$ go run server.go

Then, in another terminal, hit our router with a curl statement.

$ curl http://localhost:3000/test
Welcome!

Sweet!

Models

When building webapps in go, I tend to modularize the components as much as possible, both for testing purposes and readability. Models are one example of a piece of functionality I usually break into a separate package.

First, we need to create a directory within our application for the new package. Since I want it to be referred to as models, I'll name the directory the same. This is not required, but I find it to be a good convention.

$ mkdir models

Now let's add a file in the models directory to represent the structure of our user resource. I'll call it something crazy like user.go.

You'll notice two major changes. First, we added an import statement for our newly created models package. Second, we added a new handler to respond to "/user/:id" for retrieving a user. For those unfamiliar with this pattern, :id represents a parameter we can retrieve from the path, which we do to populate the Id field of our user. We also call json.Marshal on our user, which will decode our user into a JSON representation, and deliver that to the client.

Sweet! We have our example user. But do we really want to deliver the user with capitalized field names? Probably not. We could try to use lower case field names on the user struct, but then the fields will no longer be exported and available in our main package.

The documentation for the json package tells us that we can "alias" field names to be whatever we want using struct tags.

Controllers

One thing you may begin to notice is that our server.go is getting rather bloated with handlers. This is another piece of functionality I typically refactor into a package. Let's do that into a package called controllers.

Fin

That's the end of the tutorial on setting up a basic webserver with golang. We've created an httprouter instance, a model for our user resource, a controller for our user resource, and finally wired them all together.

Next time, we'll add a backend to get a true webservice feel. Check it out.