I turned into a Gopher abut 10 months ago and have never looked back. Like many other gophers, I quickly found the simple features of the language quite useful to quickly build fast, and scalable softwares. When I was initially picking up Go, I was playing around with different multiplexers available to be used as an API server. If you are coming from a Rails background like me, you probably would also have struggled in building all the Given features which one can get from Web Frameworks. Coming back to the multiplexers, I found 3 to be quite useful, viz., Gorilla mux, httprouter and bone (ordered in the ascending order of their performance). Even though bone had the best performance, and also it had a simpler handler signature, for me it still was not mature enough to be used in the production environment yet. So, I ended up using httprouter. In this tutorial, I would build a simple REST API server with httprouter.
In case you feel lazy and you just want the code, you can directly check my github repository here.
Let us begin. First create a basic endpoint
In the above snippet,
Index is a handler function and needs to have three input parameters as input. This handler is then registered to the path
GET /in the
main function. Now compile and run your program and go to
http://localhost:8080 to see your API server in action. Click here to get the code so far.
Now lets add a little bit of complexity to our
API. We now have an entity called
Book which can be uniquely identified with the field
ISDN. So let us create a couple of more actions, viz.,
GET /books and
GET /books/:isdn representing the Index and Show actions respectively. Our
main.go file now looks like :
Now if you try to request
GET https://localhost:8080/books, you get the following response
"title": "Silence of the Lambs",
"author": "Thomas Harris",
"title": "To Kill a Mocking Bird",
"author": "Harper Lee",
These were the two entries of books which we hardcoded into the
main function. Check here to for the code so far.
Lets refactor our code a bit. So far we have all the code in just one file,
main.go. Lets move them to separate files. We now have a directory :
Lets move all the
JSON response related structs to
responses.go, the Handler functions to
handlers.go and the
Book struct to
models.go. Check here to for the code so far. Now, lets jump on to write some tests. As you know, in Go the
*_test.go files are for tests. So lets create a
We use the
httptest package’s Recorder to mock the Handlers. Similarly you can also write tests for the handler
Lets refactor a bit more. We still are defining all the routes in the
main function, our handlers look a bit verbose and can be made a little DRY, we are still lacking some log messages in the terminal, and lets also add a
BookCreate handler to create a new Book.
First, lets DRY out the
I created two functions,
writeOKResponse for writing responses with
StatusOK and a model or a slice of models returned in it, and
writeErrorResponse which writes a JSON error as a response in case of any expected or unexpected errors. Like any good gopher, we should not panic. I also added a function called
populateModelFromHandler which unmarshals the contents from the body to any model (struct) you want. In this case we are using in the
BookCreate handler to populate a
Now, lets take care of the logging. We simply create
Logger function which wraps around the handler functions and prints log messages before and after execution of the handler function.
Lets take care of the routes now. First, define all the routes in one place, say
Lets make a function
NewRouter , which can be called from the
main function, which reads all the routes defined above and returns a usable
httprouter.Router. So create a file
router.go. We will also wrap around the handlers with the newly created
Your directory should now look like
Check here for the full code base.
This should get you going to start writing your own API server. You would of course need to put your functionalities into different packages, so one good way could be
│ ├── books_test.go
│ └── books.go
│ ├── book.go
│ └── *
│ ├── *
| ├── *
You can also put
models, All the routes functionalities under another package called
app if you have a big monolithic server. Just keep in mind, go is not like Java or Scala and there cannot be cyclic package calls. So you have to take extra care with your package structure.
Thats all and hope this tutorial was useful. Cheers !