Arrow of time
Arrow of time
Introduction to Go for Python / Django developers

This is a gentle introduction to Go for primarily meant for Django developers. Admittedly, it is in some ways like ...

This is a gentle introduction to Go for primarily meant for Django developers. Admittedly, it is in some ways like comparing apples and oranges. Since Go is a language (with a batteries-included standard library) and Django is a web application framework, this guide will make some choices on how to make Go useful for web application development. There is a very large number of Go libraries, frameworks and micro-frameworks out there, and more are developed every day, so the choices presented here should be periodically re-evaluated, just to see if something better is available among the open source projects.

This guide assumes at least a passing familiarity with Go's syntax, or at least with a C-like language. If you have learned C in university, that is excellent, since it will help you greatly. If not, you are probably familiar with JavaScript (since you work with web apps), and it is better than nothing. I will not explain entirely how Go works here, I will only point out some details which may be useful to someone just starting to learn it. On the other hand, I will assume you know Django fairly well.

And to resolve the issue at the start: why learn Go in addition (or instead of) Django? For me, it's very simple: performance. After working with both, I think developing in Python / Django is faster and more convenient (Django particularly goes to great lengths to simplify web app development - the admin interface itself is a little miracle), while its execution performance, well, is better not mentioned in polite society. Go at least is compiled, and since I have a very long history with C, it's more like coming home. For a compiled language, as you will probably see in this guide, Go is actually very script-like. In particular, there is a lot of reflection data being recorded (and used), and, surprisingly, almost arbitrary data can be added for runtime inspection in struct tags. This, together with other nice features such as the garbage collector makes it a much "softer" language than C or C++. By its nature, Go very much resembles "C with a lot of syntax sugar".

The setup and the "Hello, World"

You should have the latest version of Go installed. Please do not use the version which comes with e.g. Ubuntu 14.04 LTS, since it's like working with Python 2.4 or Django 1.3, i.e. ancient. Unless you have an extremely good reason, you should install (unpack) Go in the default location, which is /usr/local/go for Unix-like systems, and c:\go for Windows (see the docs!). If you have installed Go in the default location, you only need to create the GOPATH environment variable. It will point to your user's Go working directory, aka "workspace", used to download and build third party dependent libraries, etc. It can be an arbitrary directory NOT within the directory where you've installed Go. On Linux it is customary to have it in ~/go. While you could also create your projects in this directory, following the prescribed directory naming strategy, it is not a requirement.

Before proceeding, you need to modify your system's PATH environment variable to include the bin subdirectory of your Go installation and the bin subdirectory of your GOPATH workspace. The first is because you need to use the Go compiler and system tools, and the second is because third party libraries and utilities will sometimes have their own executables.

For the "Hello, World" program, simply make a directory named "helloworld" anywhere, and in it a file named main.go with the following contents:

package main

import (
        "fmt"
        "os"
        "time"
)

var days_of_week = [7]string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}

func main() {
        fmt.Println("Hello, World")
        now := time.Now()
        wday := now.Weekday()
        fmt.Printf("It is %s!\n", days_of_week[wday])
        if wday == time.Friday {
                f, err := os.Create("hello.txt")
                if err != nil {
                        panic("Cannot create file!")
                }
                defer f.Close()
                _, err = f.WriteString("TGIF!\n")
                if err != nil {
                        panic("Cannot write file!")
                }
        }
}

Go is a compiled language, and to create the executable binary, you need to issue the go build command, while in the same directory where main.go is. The result will be an executable file named helloworld, named after the directory where main.go is located. You can start the program with ./helloworld.

The go build command will build all *.go files, and one of them needs to contain the main() function. By convention, this file is named main.go. If you are creating a program (as opposed to a library), you need to put all the top-level code in the package labeled main, and this is what the first line of code does. Somewhat similarly to Python, the "import" statement pulls in external packages. As opposed to Python, the package names are proper strings. Functions are defined with a func keyword, and the single executable line of code calls the Println function in the fmt package.

About Go

I'd like to illustrate some properties of Go on the example code above, which need to be clear for starting any kind of development:

  • Go is case-sensitive, like Python. In fact, Go has a peculiar requirement for cases in one aspect of the code: all things which are to be "exported", i.e. available to other code outside the package they are created in, need to be named starting with an uppercase letter. For example "fmt.Println" is accessible from other packages, while "fmt.println" isn't. One other thing: package names are all lowercase.
  • Go is strongly typed, unlike Python. While type names are not always required, variables always have a type, and the type is unchangeable.
  • In Go, functions can return more then one value, like Python. Not all values are required to be received by the caller, though. You can receive what you need, left-to-right, and the unreceived return values are ignored. The special character "_" (underscore) means a value which is explicitly discarded.
  • In go, there are no exceptions (unfortunately), unlike Python. Errors are returned in a C-like fashion, are of a special type (actually, an interface named "error"), and the receiving variable is most often named err. It needs to be checked after every function call which could fail. Yes, it is tedious.
  • In go, actions can be deferred, differently from Python. The very convenient defer keyword postpones the execution of a function call until the current function exits. In the above example, the f.Close() is guaranteed to be executed in all cases, even when a panic() call happens. Read more about it here. In Python, the try..finally block could be used for a similar effect.
  • Go is garbage collected, like Python. Improvements in GC performance is one of the main reasons why you should run the latest and greatest version of Go.
  • Go is not object-oriented. Or actually, it is object-oriented up to the point where it has a standard way of packing data and code together, and some convenient syntax sugar to make it practically usable, but without inheritance, polymorphism, or other features associated with having "classes." On the other hand, Go supports interfaces a bit like Java does it, and every data type can have methods associated with it. While in Python, an int can have methods because it is an object, Go is similar to C in the fact that almost everything is a "primitive" type, or POD - plain old data, and it doesn't matter as far as attaching methods to it. Constructors and the way methods are bound to data objects work very differently in Go. Read more about it here.

There are a lot of other aspects to Go, and this is only an introductory text. Effective Go is a good high-level overview of the language and its environment, and getting familiar with the standard library is a must.

Picking Django-like libraries

Here's a small selection of libraries which are useful for web development with Go:

To install the libraries, use go get in the following way:

go get goji.io
go get gopkg.in/flosch/pongo2.v3
go get github.com/jinzhu/gorm
go get github.com/gorilla/sessions
go get github.com/gorilla/context
go get github.com/codegangsta/negroni
go get github.com/goincremental/negroni-sessions
go get github.com/goincremental/negroni-sessions/cookiestore

They will be installed in your GOPATH workspace, and you should inspect the directory structure created as a result of the commands. The go get command enables a very distributed way of storing and referencing code. It has a role similar to pip install, though the low-level details are very different.

The reason why there are a lot of libraries to include here is that Go by itself provides only the basic functionalities for writing web applications. While a minimal "hello, world" application could be written using only the standard Go features, it would not support parametric URLs, sessions, or any other real-world requirements.

...to be continued...


C++ Atomic Types / Memory Barrier Performance (or: do we need CPU caches?)

A friend of mine, a computer scientist working on memory consistency models theory in C and C++, has relayed to ...

A friend of mine, a computer scientist working on memory consistency models theory in C and C++, has relayed to me an extraordinary claim, which boils down to this: "using memory barriers in code for each read and write does not have an impact on performance." Now, this claim is something he's heard second hand, and since he is an extreme example of a theory-oriented guy, the validity of this claim was not something he...

Read More
Using Go for web app development

Last year I've been considering and experimenting with learning another compiled programming language, which would supplement Python which I ...

Last year I've been considering and experimenting with learning another compiled programming language, which would supplement Python which I normally use for, well... almost everything nowadays. There's really only one objective reason for this: performance. With Python, it simply never gets better, and Python 3 is a mess, with basically non-existent PyPy support. Sure, I could write performance-sensitive parts in C (or C++) and use them from Python, but... no, just no. The things I...

Read More
Why do you need an Encrypted Notepad?

If you are like me, you probably have dozens (or even hundreds) of passwords for various services and systems which ...

If you are like me, you probably have dozens (or even hundreds) of passwords for various services and systems which you either don't want to "remember" in your web browser, or the services are not (shockingly, I know!) browser-accessible. You have probably already remembered to search for an application for your mobile phone, or your desktop, a laptop, or whatever, which would to the job of remembering "7i48!fac3" for you. And then, like me, you've realised that there...

Read More
Why FreeBSD's pkg sucks

A not too long time ago I was a big FreeBSD user, with dozens of production installs. Gradually, I've ...

A not too long time ago I was a big FreeBSD user, with dozens of production installs. Gradually, I've been using it less and less and now I feel I must describe why, in a hopefully productive and positive fashion. In short: it's all about the packages and ports. An operating system is useless without its applications, and the currently blessed binary package management system, the pkg is seriously broken. I was very enthusiastic about pkg (then called Read More


Installing Django on Windows

Though it is obviously a blasphemy, sometimes it is actually necessary to run Django on Windows - mostly due to a ...

Though it is obviously a blasphemy, sometimes it is actually necessary to run Django on Windows - mostly due to a client having based its infrastructure around the Windows ecosystem. The "blasphemy" part comes from Django being a really nice framework which evolved on and for a Unix-like system, and it relies heavily on features like WSGI, FastCGI, and command-line tooling which are foreign to the Windows environment. Luckily, the compatibility is improving, by features...

Read More
Online.net physical ARM-powered cloud

Online.net is a French hosting company offering the usual range of services from simple web hosting for 1 € / mo ...

Online.net is a French hosting company offering the usual range of services from simple web hosting for 1 € / mo to dedicated servers, but with a twist I haven't seen before: their offer of dedicated servers is incredibly affordable! See this example: for 6 € / mo you can get yourself a dedicated VIA Nano x86 CPU powered server completely for your own usage. These CPU's performance is comparable Read More


Intel Atom vs Xeon performance

I recently got myself a small laptop, an Asus Transformer Book T100TA, and I'm surprisingly happy with it. The ...

I recently got myself a small laptop, an Asus Transformer Book T100TA, and I'm surprisingly happy with it. The current generation of these devices is what netbooks were supposed to be: very portable, with a very long battery life, but still powerful enough to be usable. In fact, I'm writing this blog post on it. Finally, both the hardware and the software (the device is running Windows 8.1 and I'd be crazy...

Read More
What Django caching can do

Nothing special here, just wanted to make a note about how simply turning on Django caching can bring a site ...

Nothing special here, just wanted to make a note about how simply turning on Django caching can bring a site's performance up from this: Server Software: nginx/1.2.1 Server Hostname: vo.ivoras.net Server Port: 80 Document Path: /api/location/1 Document Length:...

Read More
My Font Awesome to bitmap converter

A few months ago I created a small script which extracts Font Awesome glyphs and creates transparent PNG images, with ...

A few months ago I created a small script which extracts Font Awesome glyphs and creates transparent PNG images, with some fancy additional options such as shadow / emboss. My friend Saša then prettied it up a bit and we basically forgot about it - I didn't even describe it on this blog :) I've just needed an image from this project so I'd thought I'd finally write...

Read More
On constants in algorithmic complexity, and comparing apples to oranges

Can an O(n!) algorithm be faster than an O(1) algorithm? Yes, of course it can. So I came ...

Can an O(n!) algorithm be faster than an O(1) algorithm? Yes, of course it can. So I came across an interestring and almost trivial programming puzzle: given an arbitrary word and a dictionary of words, find all anagrams of the word present in the dictionary. At first I didn't care to think about the best solution for the problem and I just wrote a trivial, brute force solution as a proof of concept: from itertools...

Read More