Note Iʼm only writing this because it is my current feelings on my programing language of choice. Iʼm not trying to convince anyone that they should use Go, rather I feel like these things will probably change as I gain more experience in writing software in Go and as I learn other languages and Iʼm interested in recording how my opinion changes over time.
Criticisms of Go
Iʼll start with the things that I donʼt like. Youʼve probably heard many of these before but, I might as well record them. Note that these are in order of pain level.
I really like the way that Go manages libraries. All you need to do is
go get <import path> and then import that same import path into your code. Its really simple and I find it to be quite powerful. Of course, there is a relatively large problem here. There’s no way to state what version of that library you are using. This works fine as long as none of your dependencies make breaking changes to their APIs but, once they do, youʼll need to vendor your dependencies or fix the compatibility. There are a number of tools to help with this problem but, all of them are additional tools. There’s no built-in way to handle this, so it’s mostly the wild west out there.
Go does pass by value meaning that when you pass a variable to a function, that function gets a new variable with the same value as the one that you passed. If you want to mutate the variable in the function, you can pass a pointer to the variable instead. Unfortunately, sometimes the function that you call can still mutate your variable even if you didnʼt pass a pointer to it. In the case of arrays and structs, any modifications made in the function will be present in the original variable.
Lack of Generics
Of course, there is this one, everyone brings up Goʼs lack of generic functions. For the most part, I donʼt miss generics. I find that generics arenʼt needed for most problems. However, I know that there are certain classes of problems that generics could be considered required but, those arenʼt the sort of things that Iʼm doing. Sometimes I do wish for abstractions that could enable a library for.
It seems relatively simple but static binaries make a huge difference. They are so simple to work with, all you need to do is download the binary and run it. There is no need to install a runtime or install libraries. I love it when I run across a go project since, in general, Iʼll be able to just run it. This does have its downsides but I find that the benefit far outweighs any of the downsides. One annoyance that I do have is that Go won’t include your templates in the compiled package. I wish that you could have Go add your templates and other static assets into your binary. Luckily, there is a tool that does this (go-bindata) but, it’s a bit cumbersome to work with.
Simple Cross Compilation
I debated the ordering of this first two quite a bit as I view them to be very closely rated in terms of their importance. With Go, building for a different OS or architecture is as easy as setting
GOOS=<target os> and
GOARCH=<target architecture> if youʼve installed the cross compilers. For the vast majority of cases, that is all that it takes. It makes it very easy for me to write Go apps on my Mac and then compile them for uses on our Linux based servers. Unfortunately, there are some things that you need to consider. First is that you need to have the cross compiler support. Luckily this is fairly easy with brew as its a simple command line switch. Some of the runtime is built in C and therefore if you want good performance, youʼll need to build your application on the target OS and architecture. Luckily, both of these things are resolved in Go 1.5. Go 1.5 is completely written in Go and so youʼll no longer need to worry about having the C bits properly built for performance. That does bring up the last thing you need to consider and that is cgo. If your Go app depends on a C library, then you wont be able to utilize Goʼs great cross compilers.
Goʼs Channels and goroutines combine to make building effective concurrency easy. Goroutines are great. They quite efficient and youʼre able to spawn as many as make sense for the situation. Go takes care of scheduling them fairly. Now that you have things happening concurrently, youʼll need a way to communicate between them. Luckily, Go includes a a great way to do just that, goroutines.
I find Go to be extremely readable. Go has a very succinct syntax and it will likely be familiar to most programmers. Iʼve found that I can easily make my way through any third party library.
Great standard library
Goʼs standard library is really great. it includes a great many of the things that you might want to do. The standard library is very effective.
The way that Go handles interfaces is outstanding. You donʼt have to declare what interfaces your type implements instead, you simply implement the interfaceʼs methods and then you can use your type anywhere that accepts that interface. There are many useful interfaces built right into the standard library. Things like
io.Writer for reading and writing data. Even for things like sorting collections. Go interfaces tend to be extremely simple which makes implementing them simple as well.
While speed isnʼt at the top of my list of priorities, Goʼs speed is really nice. For the most part, I just write straightforward code and the performance is excellent. This doesnʼt mean that I donʼt that I donʼt think about performance. I do think about the performance impact of various choices but, I usually choose the simplest solution. I have yet to run into any performance issues.
As I said before, Iʼm not trying to convince anyone of anything. Iʼm merely recording my current thoughts so that Iʼll be able to look back on them in the future and see how my opinions have changed. If what Iʼve said resonates with you then, I encourage you to try out Go. I find Go to be a great language to work with and there are a great number of awesome projects being built with Go right now.