read

Last Thursday I had the pleasure of attending Andrew Gerrand's code lab "Whispering Gophers: networking programming in Go" here in Tokyo. Why is that so fascinating? Well mainly because I think it's a really cool code lab if you want to see what Go can actually do and everyone can give it a try. But about that later.

So what is Go and why should you care? According to the official website:

Go is an open source programming environment that makes it easy to build simple, reliable, and efficient software.

That's pretty generic description so let's expand it:

  • was developed at Google in 2007 as an internal language by Robert Griesemer, Rob Pike, and Ken Thompson (yes that Ken Thompson)
  • Go is statically-typed (although it does look dynamic at places thanks to a basic type inferencing system)
  • has C-style syntax but with some (minor) fundamental differences
  • contrary to C uses automatic memory management
  • is compiled (but compilation time shouldn't be a concern. Runtime speed, though, is a completely different story)

So is that all? No! There's much more to it. Some random features that I personally found interesting include:

Visibility

If you're a C++/Java/C# guy or into a language that has some kind of visibility mechanism like public/protected/package/private you will be surprise that Go does not uses that kind of stuff! Instead visibility in Go is by default at the package level. What to do when you want something to be visible from outside of the package? Uppercase it! That is exactly why this will work:


package main
import "fmt"

func main() {
fmt.Println("Hello, 世界")
}

And this will fail:


package main
import "fmt"

func main() {
fmt.println("Hello, 世界")
}

At this point all the purity nerds are probably going crazy "how can this be, exposing my internals to the world is worse than killing kittens!". Well, no. At least not for me! Over the years I come to realise that it does not matter whether you call something directly or using a method as long as it's all within your code! External API is a obviously completely different but first of all external APIs are much more rare than internal code and second of all for that you have the uppercase convention. Pretty cool little feature that wouldn't make me generate getters and setters all over my code (although indeed in Java this isn't so troublesome nowadays thanks to IDEs and stuff like Project Lombok).

Goroutines and channels

If you have worked with multithreaded code in the past chances are that you hated it as much as I do. At least that's the case for most popular programming languages. The boilerplate around it is, usually, just too annoying. Go, though, shines in this regard with it's inbuilt light threads called Goroutines and with the mechanism that let's different goroutines communicate channels. Channels are the only way goroutines can communicate between eachother. You don't get any handle or pointer to a goroutine when you create it. Ok but how do you actually spawn a new thread of execution?


package main
import "fmt"

func myFunction() {
for i := 0; i < 5; i++ {
fmt.println("Woohoo, I'm in a different thread!")
}
}

func main() {
go myFunction()
for i := 0; i < 5; i++ {
fmt.println("Main thread calling!")
}
}

The code above will make myFunction to run in concurrently thanks to the use of the go keyword! That's really all you need to do! If you would like to communicate between those two you would just need to create a channel:


func compute(channel chan uint64) {
// do some time consuming computation and put the result to "res"
channel <- res;
}

func UseAGoroutine() {
channel := make(chan uint64);
go compute(channel);
// mind your own business while compute() runs in a different thread
computed := <- channel;
// use the computed result in this thread!
}

Is that easy or is that easy? Actually the above code can be made even more concise since Go supports anonymous functions and has lexical-scope for variables but I will leave that out for now. The best part here is that they are truly lightweight so you don't have to worry too much about overusing them as they will be properly mapped to OS threads.

Utilities!

My take on Go is that it's trying to be a very modern language which tries to address all the problems development teams had over the years. "Teams" is very important here, people who all their lives programmed by themselves might not appreciate things like:

  • go fmt - this little thing will format your code according to the standard! Yes, IDEs do that also but usually you need to define all the rules yourself. Yes Python has something very similar with it's indentation system and... Well that's one of the reasons I love Python! Despite what anyone can tell you having a concise code is much more important than having this brace here and this brace here just because you like it that way. Repetitiveness here is good as it speeds up the time you need to read the code!
  • go test - yup, Go has a testing feature right out of the box! It definitely isn't the best thing out there, but it's still cool that it's part of the language itself
  • Go highly recommends creating an environment variable $GOPATH and putting all your projects in $GOPATH/src/mylittleproject/. Why is this cool? Because Go has native support for version control systems! Let's say you have your project on GitHub and want to download it, what do you do? You just execute go get github.com/user/mylittleproject/. That's a pretty neat little feature right that
  • Deployment! I don't know about you but in my life deploying things was always a nightmare. Whenever I had to do a deploy I was sure there will be some magical scripts etc. involved. In Go the result of compilation is a single binary file so it all boils down to cross-compiling your project and simply deploying it where you want. No need for external dependencies!

There is obviously much, much more good things I didn't mention here. But I'm pretty sure that once you start reading the materials I will post at the end of this post you'll find about them.

The reality slap

So is Go the best thing ever since The Muppets: Bohemian Rhapsody? Well, unfortunately, not quite! The list of things I don't like in Go goes on and on...

  • the name. Seriously, please don't call things like "D", "Go" or whatever. It's a pain in the you know what to find information about such technologies! In case of Go there's actually already a different language called Go!...
  • global state - yes, you can use global state in Go! You can try, but you will not convince me that it is a good thing
  • lack of exceptions - well this isn't 100% true as there is panic which basically works like exceptions. The thing is you shouldn't really use it, from my understanding. As a result you end up returning the, instead of your normal result, an error objects which then you can use to check if everything went ok. Before I noticed I ended up repeating the same piece of code all over the place (which to say the least wasn't neither pleasant nor good for the codebase):

  • v, err = something.SomethingThatMightReturnAnError()
    if err != nil {
    //handle me like one of your French exceptions
    }
  • everything is an error. On would think that this is good, because the creators are strict but seeing how they are inconsistent at times themselves (for instance the above error mechanism can be silenced like it is in the case of fmt.Println which does return an error object!) and how really annoying this is during development I'd really appreciate being able to make it less strict. Now even unused imports/variables will make your code fail
  • no generics - one would think "how is this possible in this day and age?" but that's the harsh reality. Go does not have generics! One might argue it's better to have no generics than to have stuff similar to Java's generics, but it's really painful to write code without them. So how do you write that generic max(T el1, T el2) method? You don't. You write a lot of them, one for each type! Ok I am not being 100% fair here because there are ways to go around this, fo instance using interface{} but it's not really the most pleasant way out!
  • because of the things I mentioned above and some other reasons it simply does not feel DRY enough and the last thing I want in my codebase is repetitive code
  • it has pointer. Ok this is more of a joke but I do have nightmares where I am back at Uni and take my C class

So in the end...?

It's been already 6 years since Go was created and it still didn't get that much traction. Yes, yes according to some articles etc. it did get the most users in X amount of time blah blah blah but still almost no one knows about it and even less people are using it! Still, I encourage you to check it out. Especially if you're looking for something between C and Java and/or want to develop highly concurrent apps! You might not be disappointed! How to start?

  1. A tour of Go will get you started with the basic syntax and constructs
  2. The spec will comfort you when you're sad
  3. As I mentioned the whispering gophers code lab is available online for everyone! The slides will take you step by step through setting up your machine, getting the necessary code and every single exercise. It's a great place to learn about goroutines, channels and how a basic gossip protocol works!
  4. You might or not be aware of this but MIT (yes, the MIT) rewrote it's whole 6.824: Distributed Systems lab in Go! After finishing the above materials dive into the wonderful world of Paxos based sharded key-value stores in Go! Personally I did only the first two labs but they were more than worth it and I'm really tempted to finish the remaining 3

As always I'm looking forward to hearing your feedback, especially if you used Go in production!

Blog Logo

Mateusz Dymczyk


Published

Image

Rants about programming...

Coding, Japan and general rants from Toyko...

Back to Overview