Yet another blog about software development

My thoughts about {Golang,Java,Cassandra,Docker,any-buzzword-here}

Go vs Java: tools

by Adam Jędro. Categories: golang / java / programming Tags: golang / go / java / programming / tools
Share this post on: Facebook LinkedIn Twitter

In Java, where I come from, there are plenty of programs that help developers in their work. Build tools such as Maven or Gradle and IDEs with their plugins actually can do (almost)everything I might want. A huge community of developers makes it easy to choose right tool to get the job done.

Golang was created with other vision in mind. A lot of tools are built-in into the language itself, allowing to get things done in a standardized and organized way.

In this post I will try to compare built-in Go tools such as fmt, test and get with their counterparts available in Java ecosystem.

Formatting

Go comes with go fmt which is considered by the community as the most useful and friendly tool. It simply reads input and produces formatted output based on Go convention.

go fmt can operate on file or folder processing .go files recursively but please note that go fmt hello.go will print formatted file to standard output. Use -w to format file in place.

I don’t want to cover technical details such as how files will be formatted so detailed description can be found here and here.

Java, not amazingly, does not have built-in source code formatter. There is a couple of ways to keep code formatted:

  • IDE/external formatter
  • Code review :)

In the project that I am currently involved at we agreed on strictly determined style. Repository always contains config files for our IDEs (Eclipse and Idea) which are imported once at project setup stage and thus we use IDE as formatting tool with help of pre-commit hooks and code review board.

Both solutions gives us same result in a similar way - but Go authors decided to create one source of truth for all developers, which is not common in other ecosystems, making formatting conventions standardized.

There are plenty of positive aspects of this, but I will give you the two most important ones:
* Identical formatted code is easier to read and maintain. It’s obvious.
* Team don’t need to fight about favorite style. Decision has been made. And trust me - sometimes these religious wars are very tough.

Have you ever had a discussion about formatting conventions with your team? I’m sure you had.

Testing

Java has well established testing conventions based on years of experience in this area. JUnit is de-facto standard for running tests in Java. This view is confirmed by the splendid analysis done on Takipi blog.

JUnit is the Undisputed King of Java Libraries – With 3,345 entries, 64% of Github’s top Java projects imports are set on JUnit.

Year by year (2015 and 2016) JUnit is placed as the most famous and useful Java library.

It’s not surprising that Go has its own testing tool. It’s another tool that community treats as standard and, in fact, it is. There are libraries such as https://github.com/stretchr/testify to help developers in their daily work but under the hood one can still find native go test support.

Test suites sit in *_test.go files. This suffix is required for file to be recognized by go test as test file.

Let’s practice on one of the most trivial example - we want to know if number is either odd or even.

// file even.go
package main

import (
	"fmt"
)

func isEven(a int) bool {
	return a & 1 == 0
}

func main() {
	fmt.Println(isEven(8))
}

This is full program that you can run. It tells if number is even. It is as simple as that.

Let’s see how we can test this code.

// file even_test.go
package main

import "testing"

func TestShouldReturnTrueIsNumberIsEven(t *testing.T) {
	if !isEven(2) {
		t.Errorf("%v is even but isEven() returned false!", 2)
	}
}
func TestShouldReturnFalseIsNumberIsOdd(t *testing.T) {
	if isEven(3) {
		t.Errorf("%v is not even but isEven() returned true!", 3)
	}
}

Looks easy and in fact it is easy!
What are the rules of writing tests in Go?
* Test file eg. even_test.go sits near even.go, in the same package.
* Test methods have to start with Test prefix.
* go test will run tests in current package
* Each test method has to take pointer to testing.T struct. It helps managing test state, by using testing.T we can fail, skip or run test in parallel.
* Assertions are often plain if statements - unless you use third party libraries.

It’s only small part of the Go testing power. There are also benchmarks, parallel tests and examples to cover, which I will do in the next posts. For now, please refer to the excellent go documentation about test support https://golang.org/pkg/testing/

Dependency management

Built-in dependency manager is simple. Just run go get github.com/golang/glog and appropriate tool will download package to GOPATH/src/<import-path>. This can be a drawback because, as you know, go convention is to leverage one common workspace for all golang projects. What if we need two versions of the same package for different projects? Well, we need to use vendoring. Because of simplicity of go get, we can’t define a tag, commit hash or even a branch(please read) that we want to download - this is another drawback.

go get tool supports following repositories:
* git
* svn
* hg
* bzr

Go, starting from 1.6, supports also a feature called vendoring. There is a great explanation on the official Golang page.

In general go get can be described as

Tool that downloads go code to $GOPATH and let you do everything you need with this code.

rather than:

Tool that takes care of project dependencies lifecycle.

glide is a great package manager for go. It can manage dependencies based on glide.yaml config file utilizing vendor directory so we do not need to worry about the concern I described in the first paragraph. You can expect that every time you download dependencies glide, with the help of glide.lock, will download the same version of code - it’s mentioned in Glide docs as reproducibly fetching of the dependency tree.

In Java world there are a couple of dependency managers but two of the most famous ones are Maven and Gradle. They are much more powerful tools than Glide but they were invented with dependency management in mind.

Go differs from Java, in Java world you do not need to download the source code library and then compile it yourself. You can just add dependency in the form of jar to classpath and that’s all. This can be considered the biggest difference between these languages: Java code is executed by VM whereas Go compiles to native code.

Summary

This post is not supposed to answer the question which language is better. I came to Golang from Java and thus I wrote about tools and conventions that seem different to me. I hope I have given you some insights regarding what the Goland tools look like in comparison to Java.


Feel free to share this post if you like it. Facebook LinkedIn Twitter
comments powered by Disqus