go

It’s time to GO

I have always been a big fan of trying new technologies, techniques and programming languages. This time I had the opportunity to spend some time researching the GO programming language.

GO is an open source programming language and on the GO web page, golang.org, they claim it will help you write simple, reliable and efficient software.

When it comes to programming languages, my personal opinion is that language should be a help to you as a programmer and that language should have a syntax that is easy to understand. This helps a lot when you (or anyone else) need to manage and maintain the code in the future.

Even if the language has syntax that is powerful, complex and can make your program super-efficient, you should think twice before using it as someone needs to take care of it in the future. However there are exceptions when you must use it for making your software efficient, but then as the good programmer you are the code comments has excellent description of what the code really does.

At the first glance of GO its syntax looked very familiar with C and Python which are the most common languages I use on a daily basis at work.

package main

import "fmt"

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

In addition to the basic test programs like the example above, I made a basic port for the product I develop and maintain at work. I can’t go into any detail about what the product actually does because it is confidential, but it is a fairly large product based on its amount of code (> 300k LOC). The port was not feature complete but enough feature were implemented so I got a good feeling that GO would have suited this product good, as a bonus with the built-in cross compile I got an fully functional amd64 port of the product even if the target of the product is for arm64.

The port was easy to understand and follow and the amount lines of code was significantly less and elegant in some areas than the C variant. However the resulting static binary was larger due to the nature of GO linking, a few years ago it would matter but today a MiB here or there is not that critical.

I made a larger (and not the most good-looking) code example in GO during my reasearch of the language where I did a concurrent calculation of an mandelbrot set. The mandelbrot function is a direct port of the wikipedia pseudo code with the addition of an wait group and a go-function for calculation of a specific line.

package main

import "fmt"
import "image"
import "image/color"
import "image/png"
import "math/cmplx"
import "os"
import "runtime"
import "sync"

func draw(img *image.NRGBA, x int, y int, value uint32, iterations uint32) {
	c := color.NRGBA{
		R: 0,
		G: 0,
		B: 0,
		A: 255,
	}
	if value < iterations {
	 	i := value % 128
		q := uint8(255 - i * 2)
		c = color.NRGBA{
			R: q,
			G: q,
			B: q,
			A: 255,
		}
	}
	img.Set(int(x), int(y), c)
}

func mandelbrot(img *image.NRGBA, w uint32, h uint32, iterations uint32, cores int) {
	x_inc := float64(4.0) / float64(w)
	y_inc := float64(4.0) / float64(h)
	y := 0
	var wg sync.WaitGroup
	concurrentGoroutines := make(chan struct{}, cores)
	for b := -2.0; b < 2.0; b += y_inc {
		wg.Add(1)
		go func(b float64, y int) {
			defer wg.Done()
			concurrentGoroutines <- struct{}{}
			x := 0
			for a := -2.0; a < 2.0; a += x_inc {
				n := uint32(0)
				c := complex(a, b)
				z := complex(0, 0)
				for cmplx.Abs(z) < 2 && n < iterations {
					z = z * z + c
					n += 1
				}
				draw(img, x, y, n, iterations)
				x += 1
			}
			<-concurrentGoroutines
		}(b, y)
		y += 1
	}
	wg.Wait()
}

func main() {
	fmt.Println("Using", runtime.NumCPU(), "cores")
	img := image.NewNRGBA(image.Rect(0, 0, 3840, 2160))
	mandelbrot(img, 3840, 2160, 1024, runtime.NumCPU())
	f, err := os.Create("image.png")
	if err != nil {
		panic(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		panic(err)
	}

	if err := f.Close(); err != nil {
		panic(err)
	}
}

mandelbrot

Does the claims of GO help you write simple, reliable and efficient software?

I will agree for now that GO will help you write simple and efficient software, the language syntax is simple and its built-in support for concurrency make it simple to utilize your CPU to the max. I still need to compare the generated machine code between C and GO before I can do a final statement about how efficient GO is, and for reliable part I need to do something bigger and put it into daily usage before I make a comment.

I will probably continue to use GO when writing small utilities (instead of Python) to get myself familiar with the large amount of packages that are available and some day I might introduce the GO language as a part of my collection of daily programming languages.