Learning Golang with a Java Background: A Developer’s Journey — Part I

Saravanakumar Arunachalam
5 min readJan 8, 2025

--

Transitioning from Java to Golang can be an exciting and challenging experience. As a Java developer exploring Golang, I want to share my journey, highlighting key differences and the reasons why Java developers might consider learning Go. Both languages have distinct strengths, trade-offs, and use cases, making a comparison both insightful and practical.

Why Transition from Java to Golang?

Java, a widely-used object-oriented language, boasts robust libraries for web development (e.g., Spring Framework), automatic garbage collection, and a rich ecosystem. However, its high memory footprint can be a drawback for web services. For example, a Spring-based executable JAR typically requires a minimum of 512 MB of memory.

In contrast, Golang (Go) is celebrated for its efficiency in concurrency handling, memory management, and smaller memory footprints for executables. Yet, Go introduces its own learning challenges, such as its limited object-oriented programming (OOP) support and the concept of pointers, which might be new to Java developers.

With these differences in mind, let’s explore some practical comparisons between Java and Go.

Core Differences Between Java and Golang

Main Method

In both languages, the main method serves as the entry point, but their syntax differs.

Java Example:

public static void main(String[] args) {
// Your code here
}

Golang Example:

func main() {
// Your code here
}

Data Types

Here’s a comparison of common data types in Java and Golang:


| **Java** | **Golang** |
|------------|--------------|
| byte | byte |
| char | rune |
| boolean | bool |
| short | int16 |
| int | int32 |
| long | int64 |
| float | float32 |
| double | float64 |
| - | complex64 |
| - | complex128 |

Operators

Both Java and Go share many operators, but there are notable differences:

  • No Increment/Decrement (++/ — ) in Go: Use x += 1 or x -= 1 instead.
  • No Ternary Operator in Go: Use if-else statements for conditional expressions.
  • Bitwise Complement (~) in Java: Go uses ^ for bit-flipping.
  • Right Shift (>>) Behavior: In Go, it’s always unsigned, while Java has both signed (>>) and unsigned (>>>) shifts.
  • No instanceof in Go: Use type assertions or reflection for type checking.

Control Flow

Conditionals (if, else if, else)

  • Java: Parentheses are mandatory around conditions.
  • Golang: Parentheses are omitted, and variables can be declared within the if statement.

Java Example:

if (x > 0) {
System.out.println("Positive");
} else if (x < 0) {
System.out.println("Negative");
} else {
System.out.println("Zero");
}

Golang Example:

if x > 0 {
fmt.Println("Positive")
} else if x < 0 {
fmt.Println("Negative")
} else {
fmt.Println("Zero")
}

Switch/Case

  • In Go, break statements are implicit, while Java requires them to prevent fall-through.
  • Go supports multiple values per case and allows expressions in cases.

Java Example:

switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
default:
System.out.println("Other Day");
}

Golang Example:

switch day {
case 1:
fmt.Println("Monday")
case 2:
fmt.Println("Tuesday")
default:
fmt.Println("Other Day")
}

Loops

Go offers a single for loop construct that replaces Java’s for, while, and do-while.

Java Example (for loop):

for (int i = 0; i < 5; i++) {
System.out.println(i);
}

Golang Example (for loop):

for i := 0; i < 5; i++ {
fmt.Println(i)
}

Object Creation

Go’s structural composition differs significantly from Java’s class-based approach.

Java Example:

class Person {
String name;
int age;

Person(String name, int age) {
this.name = name;
this.age = age;
}
}

Person p = new Person("Alice", 25);

Golang Example:

type Person struct {
Name string
Age int
}

p := Person{Name: "Alice", Age: 25}

Error Handling

Java uses exceptions, while Go emphasizes explicit error handling.

Java Example:

try {
// Code that may throw an exception
} catch (Exception e) {
e.printStackTrace();
}

Golang Example:

if err != nil {
fmt.Println(err)
}

Go also introduces defer to schedule cleanup tasks, which execute when the function ends.

Access Modifiers

Access modifiers are an important concept in programming as they control the visibility and accessibility of classes, methods, and variables. They determine what can be accessed from outside the module or class we are writing. In Java, there are four main access modifiers: private, public, protected, and default. Similarly, in Go (Golang), the concept is simplified by using the case of the first letter of the variable or method/function name to determine its visibility.

Java Access Modifiers:

1. Default: When no access modifier is defined, the default access level is used. It allows access only within the same package.

2. Private: The private access modifier restricts access to within the same class only. It is the most restrictive access level.

3. Public: The public access modifier allows access from any other class. It is the least restrictive access level.

4. Protected: The protected access modifier allows access within the same package and also to subclasses.

In Go, identifiers starting with an uppercase letter are exported (public) and those starting with a lowercase letter are not exported (private).

Example in Java:

    class MyClass {
int x; // default - accessible within the package
private int y; // private - accessible within the class
public int z; // public - accessible from anywhere
protected int a; // protected - accessible within the package and sub classes
}

Golang


type MyStruct struct {
X int // exported
y int // not exported
}

func (m *MyStruct) MyMethod() { // exported
// code
}

func (m *MyStruct) myMethod() { // not exported
// code
}

Key Differences and Takeaways

  • Paradigm: Java focuses on object-oriented programming, while Go leans toward simplicity and structural composition.
  • Memory Footprint: Go executables are smaller, making it suitable for microservices.
  • Concurrency: Go’s goroutines are lightweight compared to Java’s threads.
  • Learning Curve: Java developers may find Go’s lack of OOP and pointers challenging initially.

Both Java and Go have their strengths and are suited to different scenarios. For a developer transitioning to Go, understanding these differences and adapting to Go’s minimalistic design can lead to building efficient, high-performance applications.

If you’re interested in diving deeper into collections in Golang, you can explore all the details in Part II of the series: Learning Golang with a Java Background — A Developer’s Journey — Part II. This article focuses on arrays, slices, maps, and sets in Golang, comparing them to their Java counterparts to help developers transition seamlessly. Whether you’re curious about dynamic resizing with slices or how to simulate sets using maps, it’s all covered in the write-up. Check it out to enhance your understanding!

Looking Ahead: Threads, Goroutines, and Channels

This is the first part of my journey in comparing Java and Golang. In the next part, I will delve deeper into Java Threads and Go’s Goroutines and Channels. These constructs are vital for handling concurrency in both languages and reflect their unique philosophies in software design.

Stay tuned for an in-depth exploration of how Java’s multithreading model compares to Go’s lightweight goroutines, as well as how channels in Go simplify data communication between concurrent processes.

--

--

Responses (1)