Go Web Programming: MVC architecture based web app

In this article I want to talk about how to structure your MVC based app so its reusable and robust. Much of the style you are going to see in this article is based on Django (Python web framework).

Let’s start, are we going to use a framework ? No, we are going to use GoLang’s inbuilt net/http package at the core in conjunction with some handy tools from Gorilla (web tool kit). Throughout the article I’m also going to talk about the development environment in which we are going to build a tiny post publishing web app.

First things first, we are going to use a REPL (read, eval, print, loop) in the form of gin, a live build server tool which will recompile your Go app when there are any changes to the code base.

To install just do go get https://github.com/codegangsta/gin from your app directory .

We are also going to need a package dependency manager, for this I’m going to use GoDep. Godep is also smart enough to create a vendors directory and load third party packages into that folder, this is required if you want to containerize the app.

Just like earlier, to install, go get https://github.com/tools/godep .

Folder Tree Structure

Right, now that the environment is sorted, lets talk about the folder structure.

That’s a lot of folders, I’ll cover most of them as we go along but for now the most important folders to note are

templates — For holding our html

controllers — For holding our controllers

models — For holding our data models

medium.go is going to the starting point of our application

Finally, its code time, without wasting any time lets dive into medium.go

Looking at the imports, having an import order is really useful for others to understand. Here, we use negroni, a tiny middleware focused library which works directly with Go’s net/http . n.Run(":3001") will run our app on localhost:3001 , since we are using gin, from our app directory lets run gin --port:3000 , this will run a proxy server for our live reload server. Now our web app can be accessed either from ports 3000 or 3001. Of course the whole point of gin is to use it from 3000. Using gin I can skip running / building the project every time I make a change.

To install negroni, go get https://github.com/urfave/negroni

The terminal window when there is an error in our code followed by when there is none.

Now, what does the router variable hold? Good question, lets dive into router.go .

Ok this file has lots of things going on, a variable url_patterns is holding values returned from the urls package.

This is the urls package, here we define all the urls we want our application to have access to, the urls defined here are going to be used in the routers , controllers, templates packages. This way we have one file where we can manage/edit urls throughout the app. Any url we want to add to the application needs to be done here.

Going back to the routers package, after we have retrieved all the urls, we start to construct routes that are associate with controllers.

Here common is a pat object, pat is a request router and dispatcher which uses regex under the hood to match urls requests.

To install pat, go get https://github.com/gorilla/pat

At this point, we have installed quite a few packages, lets use GoDep to save the packages to a file, we can do this by hitting godep save , this will do a bunch of things, first of, it will create a Godeps directory with a json file containing all the packages required in the application including the package versions. Under any circumstance do we lose the packages from our $goroot or $gopath we can easily restore using the json by hitting godep restore , handy !!

Anyways, pat, has all your basic http methods like get, post, put, patch, delete. I have decided to use only get and post for this demo.

As you can see, each route will look something like this, i.e,

Any route that you want to add to the application needs to be done here. And to do so we need a url and a controller.

One more thing, I want to talk about in the router.go file before I head onto controllers, is the following two entries,

To serve static files, like JS, CSS and images, we use this route.
This route basically says any request with url that starts with the “static” prefix means it is going to look for a file in the static directory to be served directly.

What if we need every request that comes to our web server to undergo some processing? This is where negroni middlewares come in. Here we are saying any request with url that starts with medium needs to be sent to LoggingMiddleware first.

Let’s have a peek into middlewares.go ,

I have removed the actual implementation as that is not what we want to discuss here. The link to the entire repo is at the bottom of the article.

The LoggingMiddleware takes a request and response objects as arguments and then uses the same objects to redirect to a controller after finishing some task.


Controllers , here we go

Every entry in the router.go file is mapped to a controller in the controllers package.

A controller takes a response and a request object.

The data variable is a map of string keys holding any interface value. Will talk about this in a bit. The controllerTemplate is a string const from the templates package, holding the path to a html file. url_patterns holds the urls from the urls package.

Here is the templates.go file, holding the html paths,

Now, every controller is divided into get and post, in the LoginController the get request handler calls utils.CustomTemplateExecute from the utils package. Any template that needs to be added to the application needs to be done here.

The utils package holds any common functionality throughout the app which helps in the flow of the app

Here is the utils.go file,

CustomTemplateExecute is a function that takesa request and response object as arguments and additionally the data map variable which we just talked about, and the template path.

The values from data map variable is now available to be used in a html file via the string key.

The CustomTemplateExecute then calls for the template to be executed after parsing the html files.

Now, lets talk about the post part of the LoginController,

Post normally takes form data which is parse by calling req.ParseForm(),

Form data is now available for us to use,

The above snippet from LoginController uses the schema package to map Form data to a User struct from models package.

Let us see how the form and model look like,


As simple as that, we have a form with a text input of “Nickname” and a model with a “Nickname” field. Schema does a great job at mapping and now we can use the form value as user.Nickname. Any models that needs to added the application needs to be done here.

Note: Any changes to the html field from the user will yield in a schema error. No tampering !!


If err is not nil we re render the html, else we create a session with the value of “Nickname”. We are using a method here from the helpers package.


This helper function helps in removing any white spaces from the Form’s “Nickname” value.

Any function that helps a controller with it’s flow is put in the helpers package. We need to use our best judgement to see if a function belongs to the helpers package or the utils package. I normally put domain/controller specific functions in helpers and application/system specific functions in utils.

If you have observed, we just came across a very important topic, Sessions !

A function in the utils package is responsible for creating a session to be accessed and used throughout the application

sessions is again a Gorilla package.

Note: NewCookieStore takes an argument to encrypt, loading a hash string from the environment is a good idea.


That controller had a lot of things in it, lets move on to templates

Go has template inheritance and other handy functionalities built into the text/template package. Let’s talk about template inheritance,

Some templates I have defined,

base.html — The common template for all templates, includes CSS, JS, Nav Bar etc

home.html — Welcomes the user, and contains link to adding a post

posts.html — Shows all the posts


base.html is rendered in every call of utils.CustomTemplateExecute

In the above line, templateName is passed from a controller and is basically inserted in the template "content" block of base.html


This is how login.html would look, starts of by defining “content” block.

For every block that is declared in base.html needs to be defined in login.html or any other template passed from the controller.



Looking at home.html we can see we can use urls from the urls package.

As we are sensing, any {{ }} in html is replaced by values from data map variable from the utils.CustomTemplateExecute function.

The above snippet from utils.CustomTemplateExecute gives us access to “Nickname” in any template.

Nifty !

So far so good, what about REST urls you might ask ? Let’s head on to



posts.html contains any posts we have submitted, clicking on a post will take us to the specific post page post_view.html


Not fancy, but if you observe the url, this was basically generated by add_params function.

add_params is template function that we declared in utils.CustomTemplateExecute, any functions defined there would be available for us to use in html.

The function add_params,


The first argument is the url from the urls package, in this case

The next two arguments need to be the param name i.e postid followed by the value.

Right, now I want to talk about some snippets from the app which I feel are important to note,


Redirection from a controller can be made using a simple statement,

What if we need to pass some params ?

We use the AddParamsToUrl function from, you guessed it, the utils package.

We can use the above function in the following way,

What is models.Kwargs ?

Kwargs is a struct in models.go , which has two fields, Key and Value.

Key is the param name in the url_patterns, and Value is the value you the param name to be replaced with, in this case {postid}.

Data persistence:

This is out of the scope of this article but I am just going the pen down my thoughts here. There are ORM’s for SQL based databases like gorm, there are mature drivers for NoSQL databases as well like mgo for MongoDB.

Personally, I have used mgo and wrote my own persistence layer which can be found in the store package.

Final Thoughts

Following this architecture / blueprint helps in easily understanding the flow of the application and modularizes the app into components for robust development.

There are enough packages and tools out there to build powerful Go Web apps. There are also several frameworks out there which do a job but building your own blueprint doesn’t take too long, and gives you the ease of owning your entire code base.

I have tried to cover the most important parts of the app, but also managed to leave some parts out. I strongly encourage you to clone the repository and give it a test run. Go through the code and fiddle around with it.

Link to repo: https://github.com/priyankcommits/medium

Steps to run:

  1. Clone repo
  2. Install godep, go get https://github.com/tools/godep
  3. Install gin, go get https://github.com/codegangsta/gin
  4. Install dependencies by hitting godep save ( go get -v also works)
  5. Run using gin --port:3000
  6. Point browser to localhost:3000

That’s about it for now, do let me know what you think and I will be glad to answer any questions.

Lastly, Write in GO !!!



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store