Introduction to Go

I blogged previously about the merits of learning a new programming language every year, so taking my own suggestion, I’ve had a first look at Go. You might hear it called Golang, but that’s just the url for the website, the official language name is Go. While I probably won’t learn it in too much detail at this point in time, unless a need arises, I do believe it is a good to know what Go is all about and what it can do.

What is Go?

Go is a modern programming language created by Google in 2007. It was intended to take the best elements of traditional, established languages as well as overcome some gaps or difficulties of using the likes of C++, Java and Python. It is designed to be;

  • Quick to compile
  • Performant – fast to run
  • Simple syntax

Concurrency is built in as standard to run programs efficiently on todays multi-cores processors.

Official Website: https://golang.org There is also an online playground to code in a browser without the need to install anything. https://play.golang.org

What’s it good for?

Well, pretty much anything. It’s a general purpose language, so in theory it can be used in a multitude of places, however it really comes into its own for highly scalable web applications – not really a surprise given its origins at Google.

Who is using it?

According the internet 🙂 Docker is written in Go, as are at least some of the microservices built at Monzo.

https://monzo.com/blog/2016/09/19/building-a-modern-bank-backend

Highlights

  • Statically typed, although compiler uses type inference for ease of use
  • Concurrency built in using ‘go routines’ to simplify multi-threading
  • Compiled language. Code is compiled to a binary that can be distributed without a runtime
  • Garbage collection provided as part of the ‘Go Runtime’ which is compiled into the binary
  • Multi-paradigm language – Object Orientated (no type hierarchy) & functional supported
  • Uses Pointers! However, pointer arithmetic is not supported

Runtime?

The above seems contradictory, no runtime, but uses a ‘Go runtime’. So does it have one or not? Well yes, but not like the runtime associated with Java. You do not need a separate runtime to execute a Go program, everything is self-contained in the binary, as with apps written in C++. The ‘Go runtime’ is a library that is automatically compiled into the binary making it standalone, but giving the benefits of memory management as well as thread management (via go routines) to name but a few.

A few basics

This is not a tutorial on Go, there are plenty of them about, so just exploring a little.

Like Python, there are no semicolons, Yey! The compiler will work out where one line starts and another ends, although this does mean that curly braces have to be positioned correctly. I personally like having a open curly brace on a new line, however this will give a compiler error in Go, as it is expects it on the same line, otherwise it assumes its the end of line.

package main

import (
   "fmt"
)

func main() {
   fmt.PrintLn("Hello, world!")    
}

Variables & Constants

Go is a statically typed language, although the compiler can infer the type, making it easier to use, so no need to explicitly include the type, unless you need to. Unused variables will generate a compiler error, which is a feature I really like. There is a shorthand syntax to declare and assign a variable using := otherwise use the var keyword.

package main

import (
   "fmt"
)

func main() {
   // declare and assign an integer value
   // := shorthand syntax used to declare and assign a value
   meaningOfLife := 42
   fmt.Println("The Meaning Of Life: ", meaningOfLife )

   // declare and assign a float value
   temperature := 15.5
   fmt.Println("Temperature: ", temperature )

   // update a previously declared variable
   temperature = 16.0
   fmt.Println("Temperature: ", temperature )

   // specify a type required keyword var and the type
   var desc string = "Current temp is: "
   fmt.Printf("%s: %f\n", desc, temperature)

   // Constants
   const Pi = 3.14
   fmt.Println("Pi", Pi )
}

Go Routines

Go supports concurrency out of the box and aims to greatly simplify multi-threading. To run a function concurrently, simply prefix the function call with the keyword go, that’s it! The Go runtime manages this for you, It doesn’t necessary start a new thread (it could multiplex), the runtime will manage the all the threads and their lifecycles for you to ensure it’s fully optimised. Below is an example. This uses wait groups to illustrate how you can wait for a go routine to finish, without a wait group the program below would finish before the go routine completes (or probably before it actually starts).

Although this will run concurrently, it doesn’t necessarily spawn a new thread, we defer the management of this to the Go runtime to handle this optimally.

package main

import (
   "fmt"
   "sync"
)

func main() {
   // Create a wait group.
   // This stops the program exiting before go routine completes
   var waitGroup sync.WaitGroup
   waitGroup(2)

   // prefix the function call with go to run concurrently
   // not necessarily in a new thread, the Go runtime will manage it for us
   go countTo10(&waitGroup)
   go countTo10(&waitGroup)

   wg.Wait()
}

func countTo10(waitGroup *sync.WaitGroup) {
   for i := 0; i < 10; i++ {
      fmt.Println(i)
   }

   // Notify the wait group that this routine has finished
   waitGroup.Done()
}

Go Microservices

Go is a great fit for microservices. Go routines allows you to handle lots of current requests and no external dependencies are required to create a simple web service, in fact we can create a very basic demo web service with just a few lines of code.

package main

import (
   "fmt"
   "log"
   "net/http"
)

func main() {
   // Route the path to a function
   http.HandleFunc("/", handler)

   log.Fatal(http.ListenAndServe(":8090", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
   // Simply print to the ResponseWriter to return a HTTP response
   fmt.Fprintf(w, "Hello: %s!", r.URL.Path[1:])
}

It’s very easy to package up an application in a Docker container allowing you to deploy it pretty much anywhere.