Go vs. Java: 15 main differences

yourbasic.org/golang

The following Java code, adapted from Effective Java, implements an immutable class representing a complex number.

public final class Complex {
    private final double re;
    private final double im;

    public Complex(double re, double im) {
        if (Double.isNaN(re) || Double.isNaN(im)) {
            throw new ArithmeticException();
        }
        this.re = re;
        this.im = im;
    }

    public double realPart()      { return re; }
    public double imaginaryPart() { return im; }

    public Complex add(Complex c) {
        return new Complex(re + c.re, im + c.im);
    }

    @Override public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Complex))
            return false;
        Complex c = (Complex) o;
        return Double.compare(re, c.re) == 0 &&
               Double.compare(im, c.im) == 0;
    }

    @Override public int hashCode() {
        int result = 17 + Double.hashCode(re);
        result = 31 * result + Double.hashCode(im);
        return result;
    }

    @Override public String toString() {
        return "(" + re + (im < 0 ? "" : "+") + im + "i)";
    }

    public static void main(String[] args) {
        Complex z = new Complex(1, 2);
        System.out.println(z.add(z));
    }
}

The same program written in idiomatic Go would consist of two separate packages.

package complex

import (
	"fmt"
	"math"
)

type Complex struct {
	re, im float64
}

func New(re, im float64) Complex {
	if math.IsNaN(re) || math.IsNaN(im) {
		panic("NaN")
	}
	return Complex{re, im}
}

func (c Complex) Real() float64 { return c.re }
func (c Complex) Imag() float64 { return c.im }

func (c Complex) Add(d Complex) Complex {
	return New(c.re+d.re, c.im+d.im)
}

func (c Complex) String() string {
	if c.im < 0 {
		return fmt.Sprintf("(%g%gi)", c.re, c.im)
	}
	return fmt.Sprintf("(%g+%gi)", c.re, c.im)
}
package main

import (
	"complex"
	"fmt"
)

func main() {
	z := complex.New(1, 2)
	fmt.Println(z.Add(z))
}

Note that in this case Go uses struct values where Java uses references to objects. Also, the equals and hashCode methods are omitted since Go already defines equality for structs with comparable fields.

Main differences

Built-in types

Pointers and references

Error handling

Object-oriented programming

Learn more: Object-oriented programming in Go without inheritance.

Functional programming

Learn more: Functional programming in Go [case study].

Concurrency

Learn more: Concurrent programming in Go [tutorial].

Omitted features

Complex numbers

Strangely enough, Go has built-in support for complex numbers.

z := 1+2i
fmt.Println(z + z)

It’s the least used feature of the language. By far.

Further reading

Why Go? discusses some main reasons why Go can make it easier (than Java or Python) to write correct, clear and efficient code.

Share this page: