A Java Developer's Quick Look At Golang

By Steve Claridge on 2015-05-07.

Java has been my go-to language for years. I've tried other languages but have always come back to Java for any biggish project, just because I know it well and so it's quick and easy to build stuff. Having said that, I keep wanting to try out something new even though I probably won't switch the big-project language any time soon.

I spent about five hours poking around Golang and built a simple command-line todo app, here's my initial thoughts on the language:

Syntax.

People always complain that Java is too verbose, Go is a little more terse but I didn't feel like I was saving a ton of typing. Some nice things though:

You don't have to specify a variable's type when defining it

//java
int a = 100; //Go
a := 100

Don't need brackets in if statements. I thought this would make the statement more difficult to read but it looked fine

//java
if ( a == 10  ) { //Go
if a == 10 {

When defining arrays and slices (an array without a fixed size) in Golang, you put the brackets to the left of the type. I mis-typed these many times, so used to putting the brackets at the right

//java
String[] //Go
[]string

Function return types are also in a different place, they go to the right instead of before the function name

//java
public String hello( String s ) {} //Go
func hello( s string ) string {}

Case. I was thrown a bit by uppercase names for functions in Go's common libraries, I seem to used lower case names forever in all languages, so it was kinda weird and I mis-typed the names a number of times

fmt.Println( "hello" )
bufio.NewScanner()
os.Open

Exceptions versus error codes.

Go doesn't have exceptions, instead it uses C-style error codes that are returned by functions and checked by the caller. I really liked this as exceptions annoy me, 90% of the time in my Java code I am catching all exceptions and logging and stopping the app and nothing more. It means there's less code and no big try...catch blocks. This is probably one of my favourite things about Go, but how, I hear you say, does a Go function return an actual value as well as an error code, well.....

Functions can return multiple values.

This is one place where Go works radically different from Java (and most other common languages).

func twoNums( a int, b int ) (int, int) {
    return a * 2, b * 2
}

This pattern is commonly used to return a value from a function in the "good" use case and an error code when something goes wrong. The syntax when calling the function looks a bit confusing to begin with, especially if you want to ignore one of the returned values, in this case you use an underscore instead of a variable.

first, second := twoNums( 10, 20 )
_, second := twoNums( 10, 20 ) //we don't care about the first value

So the underscore can be used when making calls to functions when you are not bothered about checking an error code.

Some C throwbacks.

I needed to convert a string to an integer and the function I found to do that was

strconv.Atoi( "14" )

A throwback to the C and C++ function of the same name and utility. I didn't really like this, good for C programmers, bad for everyone else, the function name isn't intuitive and would not be easily found by someone who didn't know atoi() before starting with Go.

Defer is short and clean.

Go doesn't have try..finally blocks. Instead, it has a defer function that allows you to specify a function to be called later, which is commonly used to close resources. I couldn't find any concrete info on when the deferred function is called but it seems to be that it is always called when the current function goes out of scope, in other words, at the end of the current function.

func readFile( filename string ) []string {
	file, err := os.Open( filename )
	if err != nil {
		return []string{}
	}
	defer file.Close()
	
        //Read the file and return contents
}

Strong typing.

Go is very strongly typed. Don't think that just because you don't have to specify a variable's type when defining it that you can get away with doing what you want with it, Go ain't messin'.

//This compiles in Java
long a = 10;
double b = 20.3;
b = a; //But Go complains. "Cannot use a (type int) as type float64 in assignment)"
a := 100
b := 20.20
b = a;

I'm still a fan of strong-typing, so no complaints from me here.

The compiler dishes out the tough love.

Go's compiler is not taking any shit from you. Any unused imports result in an error. Any unused variables result in an error. There's no code-smells on this guy's watch. At first I thought this was a bit harsh but actually it is a good thing, throwing errors for sloppy code forces cleaner code and makes it easier to read and maintain later.

TL;DR.

I barely scratched the surface in five hours but I liked what I saw. Apparently Go really comes into its own when you start using Goroutines (threads), which I didn't. The multi-value functions results to return error codes is way better than littering your codebase with useless exception catches. Not having to enter brackets and semi-colons at line-ends are small things but they do make typing code a bit quicker and the resulting code is still easy to read.