Java to Go

7 things to keep in mind when switching from Java to Go

Bogdan Gună
4 min readOct 30, 2020
Photo by Patrick Ward on Unsplash

1. Setup is simple; the language is even simpler

Initially, setting up was a bit more programatic as things were not flashed out with the Go package manager (modules). But now, you simply download the Go installer and this will automatically set all required environment variables for you.

Installation steps here.

For the famous Hello World, in an empty directory, create a hello.go file and write the following code:

package mainimport "fmt"func main() {
fmt.Println("Hello, World!")
}

You run it by simply running go run hello.go in the terminal.

As you may have noticed, you don’t need semi-colons, naming is simple and suggestive, lower case are used for private (package) access and upper case is used for public access.

2. Creating projects is simple

You don’t need a magic IDE to create projects. Folder structure and naming is much simpler than in Java.

A simple example would look like this:

project/                 # project folder
\_ cmd/ # keep the 'main' files here (optional)
|_ examples/ # show how functions/features are used
|_ internal/ # keep private modules here (internal libs)
|_ .gitignore # tells Git what not to stage for commits
|_ .makefile # used to simplify and run Go commands
|_ go.mod # specify your dependencies here
\_ readme.md # every project needs a readme, right

The idea is that there is no rule of how to set up your project. If it’s simple enough, you don’t even need these folders. Imagine you have a simple library where the code fits in one file (it’s possible with Go, lol). Then you’ll just have 1–2 go files: library.go and library_test.go.

3. You have Interfaces

In Java, interfaces are defined as Java objects which have a contract or a set of rules (methods). These then have to be present in any class that is implementing the interface. The same thing more or less applies to Golang.

package mainimport "fmt"type beverage interface {
name() string
caffeine() int
}
type coffee struct {
shots int
}
type tea struct {}func (c coffee) caffeine() int {
return c.shots * 75
}
func (c coffee) name() string {
return "coffee"
}
func (t tea) caffeine() int {
return 45
}
func (t tea) name() string {
return "tea"
}
func howMuchCaffeine(b beverage) {
fmt.Printf("%s has %d g of caffeine\n", b.name(), b.caffeine())
}
func main() {
c := coffee{shots: 2}
t := tea{}
howMuchCaffeine(c)
howMuchCaffeine(t)
}

4. But you also have Pointers

In Java, arguments are always passed by value. Whenever you instantiate an object and you pass it, you pass the address of the created object.

In Golang, you can pass arguments both by reference (pointers), and by value. The latter is usually cheaper, more convenient and simpler to understand by new Golang programmers. However, the former can be more efficient for very large structs.

Pass by value

When you pass by value, a new copy of the passed parameter is created and passed to the called function.

type Person struct {
name string
}
func changeName(p Person) {
p.name = "Bob"
}
func main() {
person := Person {"Alice"}
changeName(person)
fmt.Println(person) // prints "Alice"
}

Pass by reference

When you pass by reference (pointer), a copy of the pointer to the same memory address is created and passed.

type Person struct {
name string
}
func changeName(p *Person) {
p.name = "Bob"
}
func main() {
person := Person {"Alice"}
changeName(&person)
fmt.Println(person) // prints "Bob"
}

5. Write once, run anywhere. Wait, what?

When I started working on my first Golang project, I couldn’t believe how nice and fast it is to make my code work on any machine. You can also have OS-specific implementation.

To build your code for a certian operating system, you simply need to set the $GOOS and $GOARCH environmental variables in your makefile for the build commands.

For OS-specific implementation, you simply need to add suffixes to the name of the files, e.g: example_darwin.go, example_windows.go, example_linux.go.

6. You don’t have Generics and you won’t miss them

Golang is simple and generics add complexity, both to the engineer and to the compiler. There is a saying that less is more, and that stands true here as well. Go is intentionally simple so you can get started quickly with it, it’s fast and you can engineer simple solutions with simple building blocks for complex problems. Nowadays we are dealing with more complex problems, so why not have something easy to use for it?

7. Publishing your code is simple

Publishing your code and importing code is simple. This is achieved using modules — these are defined in the go.mod file in your project.

This is supported by the Golang SDK and you don’t need to download or setup any additional tool.

Read about using go modules to get started.

Some resources I found useful in my journey:

--

--