Setting up a web application in Golang can be a daunting task. If you’re used to rails, you probably miss having your hand held at this point. I’m using this architecture on Refer Madness [source]. Here’s my directory structure:
I’ll break this down architecturally. At each directory level, files are only allowed to access code from directories at the same or a higher level. This means that utils can access itself and models; web can access itself, controllers, utils, and models; and models can only access itself. I do this to keep a thick line between all the layers and to avoid recursive dependencies. Let’s talk about each level individually!
main.go
main.go is my main file in charge of creating dependencies, discovering environment variables, and starting the web server. Here’s a sample:
Since main.go is on the lowest level, it has access to every other directory: in this case, utils and web. I grab all the environment variables and inject them where necessary. I create the server, injecting dependencies, and then start it on the port I want.
web
I keep my server code in the web directory, which includes some web middleware. Here’s the internal structure of the web directory:
main.go
123
-web/|-middleware/|-server.go
server.go contains the definition of my web server. The web server creates all my web controllers and adds middleware to my negroni server. Here’s an excerpt:
A server struct is a negroni.Negroni web server. I create some dependencies from utils and external packages, create a router, create controllers with the dependencies, and register the router with my controllers. I also add in any middleware I may need. Speaking of middleware, here’s an example:
This is a standard middleware definition for accessing a database session from an HTTP route. The base of this file was taken from Brian Gesiak’s blog post on RESTful Go and was modifiedto fit my needs.
controllers/
A controller is similar to the controller concept found in Rails. A controller registers its own route with the router provided and then sets up function calls. An abbreviated example:
Files that belong in the utils directory provide small levels of functionality to support the rest of the codebase. In my case, I have structs which access the request context, manipulate the session, and define a base page for specific pages to inherit. Here’s where I access the context to set the user:
Models are data structures for representing my database concepts. I use my models to access the database - I create an empty model and then populate it with a database query. Here’s an example of a model I use:
I keep my goalng templates in the views directory. Pretty basic - whatever templating engine I use, I throw it into this views directory.
public/
As usual, this directory is all my public files - css, img, scripts.
That’s cool - how do I run this?
It’s no secret that I like docker, so that’s my preferred method of running this application. If I wanted to run this without docker, I would throw the root of this directory into $GOPATH/src/github.com/larryprice/refermadness. Running go get will fetch all the missing dependencies and running go run main.go or go build; ./refermadness should run the file. If you do want to use docker (and you know I do), I start with a Dockerfile:
Dockerfile
1234567
FROM golang:1.4
RUN go get github.com/codegangsta/gin
ADD . /go/src/github.com/larryprice/refermadness
WORKDIR /go/src/github.com/larryprice/refermadness
RUN go get
And, since I also love compose, I run everything with a compose file. I use a JSC transformer, a SASS transpiler, and a mongo database, so my docker-compose.yml file looks like:
And then run docker-compose up to run all the containers and start up the server.
…And that’s that! I like setting my code up this way as a compromise between idiomatic Go and ruby on rails. I inject parameters whrever possible to keep things testable. I keep my concerns separated as much as possible. Go is fast and the syntax is clean, but there aren’t enough examples of creating full-blown web applications available. At this point, we don’t know the future of Go, but I anticipate it becoming big. Hopefully this architecture overview can help someone get started making the transition from a more traditional MVC framework to golang.
ReactJS is a component-based Javascript library for creating user interfaces. I used it extensively on recent side project Refer Madness (source code). It’s pretty neat. Let’s build some demos!
We’ll start small. We can start with the ReactJS sample and figure out what’s going on:
We create a React component Hello and we tell it what to render. When we create a Hello component, we take in an attribute called name which we then access in our component with this.props.name. When the page loads, React will render the Hello component in the element with ID “container”.
Components can have other components.
I’ve created a Name component to show the name. This component uses its children to display any content it needs to. Obviously, this is a bit contrived.
Things get more exciting when we add events. Let’s add an event to our Name component: when a user clicks this component, we’ll reverse the name.
I’ve introduced state to the component. When I want a React component to use state, I need to implement the getInitialState method to tell React what the state is when the component is created. In this case, I set the name field of the component’s state to this.props.children. When I render the component, I use the name variable I set in my state object. I add an onClick event and call a method on the component called clickme. In clickme I call the built-in setState method and update the name variable on my state object. Any other state variables on the component would remain unchanged. Any time setState is called, render is called again for this component and any children which need to be updated will also rerender.
Sometimes something happens on a child component that the parent cares about. This time, I want the parent component to know when the Name component gets a click event.
I’ve told my child component to call the method goodbye on the parent element using the property name onClicked. When the method is called Ichange the state of the Hello component and update the greeting; in this case, the Name component will be reused since it hasn’t changed.
Just a reminder that you can have multiple of any component; just be sure to not duplicate IDs!
I dynamically create as many Name components as I need. I take my list of names and map them all to React components, each of which has a different value. As above, all of these can have events or can call events on the parent component. When we create a list of components, React prefers it when we give them all key attributes. This allows React to cache the components and recreate the appropriate component when states change.
Of course this is just scratching the surface. I used ReactJS because it was fast, stable, and easy to get started learning. It gave me a different way to think about the relationship between my Javascript and the DOM. For a little bit more React you should check out the tutorials. If you hadn’t noticed, React uses a twist on the Javascript syntax called JSX. If you’re into that kind of thing, I’ve written about using Docker to compile your JSX whenever you update your JSX files - very handy IMO.
Users of ReactJS may be familiar with JSX, “a Javascript syntax extension that looks similar to XML.” JSX makes writing React components a little bit easier. I wrote a bunch of JSX components when I built Refer Madness, and I wanted to find a sane way to compile my JSX files into plain JS files. As I was already using Docker to run my server-side and my compile my SASS, I created a Docker image to compile my JSX code whenever file changes were detected.
In this case, $PWD is the directory where my JSX files live. The -v flag creates a volume in my container. The --rm flag will remove the container when I’m finished using it (for convenience). larryprice/jsx is the image I want to use. This command will watch the current directory and compile the JSX whenever it detects a file change. The generated files will be created next to the JSX files.
What’s in the image, you ask? It’s just the node:latest image with react-tools installed which automatically runs the command jsx --extension jsx --watch src/ src/. It’s fairly simple, but way easier than having to do all this myself.
If I want to use the JSX image with docker-compose alongside the rest of a web application, I might have something like this:
docker-compose.yml
12345678910
app:image:golang:1.4working_dir:/go/src/simple-golang-appcommand:go run main.govolumes:-./simple-golang-app:/go/src/simple-golang-appjsx:image:larryprice/jsxvolumes:-./public/scripts:/src
It means not having to install Node or npm on your system if you don’t already have it. Being able to compile my SCSS, JSX, and Go code all in once command was a lifesaver, and being able to recreate this environment anywhere meant keeping my computers in-sync was simple. Life, love, and Docker.
As of the writing of this post, Javascript is not allowed to modify the clipboard directly in modern web browsers. There is an HTML5 spec in draft, but it’s unclear when/if this will become stable. Should we just give up on modifying users' clipboards and possibly violating their privacy? Heck no! We’ll just use Flash.
ZeroClipboard is a library which will create an invisible Flash movie over an HTML element. Does that sound hacky to you? DOESN’T MATTER, COPIED TEXT.
ZeroClipboard is super easy to use, the only caveat being in order to use the Flash movie you’re going to have to run some kind of web server. For the simple case of this example, I’ll use ruby with the following config.ru:
12345678910111213141516171819202122232425
require'bundler/setup'require'sinatra/base'# The project root directory$root=::File.dirname(__FILE__)classSinatraStaticServer<Sinatra::Baseget(/.+/)dosend_sinatra_file(request.path){404}endnot_founddosend_file(File.join(File.dirname(__FILE__),'public','404.html'),{:status=>404})enddefsend_sinatra_file(path,&missing_file_block)file_path=File.join(File.dirname(__FILE__),path)file_path=File.join(file_path,'index.html')unlessfile_path=~/\.[a-z]+$/iFile.exist?(file_path)?send_file(file_path):missing_file_block.callendendrunSinatraStaticServer
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8"><style>#copy:hover{cursor:pointer;}</style></head><body><buttonid="copy"data-clipboard-text="you should be more careful with your clipboard"> Copy Something!
</button></body><script type="text/javascript"src="ZeroClipboard.min.js"></script><script type="text/javascript">window.onload=function(){newZeroClipboard(document.getElementById("copy"));};</script></html>
This use case is simple: I create a button which the user will click to copy text to my keyboard. The text I want to copy is included on the element with the data-clipboard-text attribute. I initialize a ZeroClipboard client with new ZeroClipboard(...). The application can be run with rackup: try it out for yourself!
SASS is a delightful way to write CSS, but compiling SASS for your web application might not be the most obvious task. There are different installation methods, most of them involving cluttering up your filesystem with external dependencies. Compiling SASS is easy when you’re doing rails or sinatra-work, but I demand to write code in a compiled language. So I created a docker image to compile SASS code automatically called larryprice/sass.
Running this image is easy. Let’s say I have some SASS code:
$ docker run -v /home/larry/test-project/public/css:/src --rm larryprice/sass
That’s it. The directory /home/larry/test-project/public/css (containing my SASS code) is now being watched by the SASS compiler. Any time I make a change to a file in that directory, my code will automatically be recompiled. The above command runs the SASS watcher in the foreground, which allows me to see any compile errors in my terminal window. If I wanted to run the SASS compiler in the background, I just have to add the -d flag:
1
$ docker run -v /home/larry/test-project/public/css:/src --rm -d larryprice/sass
If my project is using docker-compose, I could add an image in my docker-compose.yml to run the SASS compiler alongside my application. For instance, if I’m running a web application with go:
docker-compose.yml
12345678910
app:image:golang:1.4working_dir:/go/src/simple-golang-appcommand:go run main.govolumes:-./simple-golang-app:/go/src/simple-golang-appsass:image:larryprice/sassvolumes:-./public/css:/src
Now, running docker-compose up would also run the SASS compiler.
I like using docker-compose in these situations as it limits the number of conflicting tools installed on my host machine. If I ever decide that SASS is the worst or that ruby is the devil, all I have to do is docker rmi larryprice/sass. No need to run find commands for every file with sass in the title; just a single, simple command to destroy all evidence.