Skip to main content

Command Palette

Search for a command to run...

Getting Started with Go (Golang) for Java Developers

Updated
β€’6 min read

If you're a Java developer curious about Go (also called Golang), you're in for an exciting and refreshing experience. While Go is simpler in syntax and tooling, it’s incredibly powerful and engineered for concurrency, performance, and developer productivity. This guide will help you transition smoothly from Java to Go.


Philosophy and Design Intent


Go was designed at Google with simplicity, speed, and ease of deployment in mind. It eliminates unnecessary complexity common in many languages (including Java) by:

  • Avoiding inheritance and generics (until Go 1.18+)

  • Having a lightweight type system

  • Using composition over inheritance

  • Compiling to a single binary with zero dependencies


Go Project Structure


No more src/main/java, pom.xml, or build.gradle. A Go project embraces simplicity and flat structure.

πŸ—‚οΈ Minimal Structure:

myapp/
β”œβ”€β”€ go.mod         # Module definition (like a minimal `pom.xml`)
β”œβ”€β”€ main.go        # Entry point with `main()`
└── utils.go       # Reusable helper functions or logic

πŸ”§ Initialising a Project

go mod init myapp

This creates a go.mod file that defines the module name and tracks dependencies.

πŸ“ Typical Folder Layout for Larger Projects

myapp/
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ cmd/              # Main application entry points
β”‚   └── myapp/
β”‚       └── main.go
β”œβ”€β”€ internal/         # Private packages not to be imported by others
β”‚   └── config/
β”œβ”€β”€ pkg/              # Exported packages that can be imported by other projects
β”‚   └── logger/
β”œβ”€β”€ api/              # HTTP handlers or gRPC APIs
β”œβ”€β”€ models/           # Data models or structs
β”œβ”€β”€ utils/            # Helper utilities
└── test/             # Additional test data or integration tests
  • cmd/ β€” entry points like main() (can support multiple binaries)

  • internal/ β€” accessible only within your module (like Java’s private)

  • pkg/ β€” reusable logic (like Java libraries)

  • api/ β€” handles incoming requests, typically with net/http or gin

  • models/ β€” represents your domain structs

πŸ“¦ Packages = Directories

Each directory is a package. Files in that directory should start with:

package packagename

To use them:

import "myapp/utils"

πŸ§ͺ Run and Build

go run main.go      # Compile and run
go build -o app      # Build binary

This structure encourages modular, testable, and production-ready Go applications with minimal boilerplate.


Object-Oriented Concepts


Go doesn’t have classes in the traditional Java sense. Instead, it offers object-oriented features through structs, interfaces, and methods, without requiring everything to be wrapped inside a class.

Why Java Uses Classes

Java is a class-based object-oriented language, and every function, including main, must reside inside a class. This is rooted in Java’s design:

  • Encapsulation: Grouping data and behavior into classes.

  • Inheritance: Sharing and extending behavior using class hierarchies.

  • Polymorphism: Achieved via subclassing and interfaces.

  • Everything is an object (except primitives), so classes are the foundation.

Go, however, moves away from this requirement by focusing on simplicity and practical design:

  • No classes β†’ Uses structs and interfaces.

  • No inheritance β†’ Encourages composition.

  • No constructors β†’ Uses simple factory functions.

  • No access modifiers β†’ Capitalized names are exported (public), lowercase are not.

Structs

Go uses structs to define complex data types (similar to Java POJOs):

type User struct {
    Name string
    Age  int
}

Methods

Methods are functions associated with a type (like attaching a method to a struct):

func (u User) Greet() string {
    return "Hello, " + u.Name
}

You can attach methods to any user-defined type, not just structs β€” a major difference from Java.

Interfaces

Go interfaces are implicit. If a type implements the methods required by an interface, it satisfies the interface β€” no implements keyword needed.

type Greeter interface {
    Greet() string
}

func greetAll(g Greeter) {
    fmt.Println(g.Greet())
}

This leads to more flexible and decoupled designs, as interfaces are satisfied automatically.


Syntax Differences


Program Structure

JavaGo
Classes and methods inside classPackages and functions
public static void main()func main()

Java:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

Go:

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}

Go eliminates class declarations and lets you write logic directly in functions.

Variable Declarations

JavaGo
Typed and untyped variablesSupports both; also allows shorthand

Java:

int age = 30;
String name = "Alice";

Go:

var age int = 30       // explicit type
name := "Alice"        // inferred type (shorthand)

Functions

JavaGo
Methods inside classesTop-level func declarations

Java:

int add(int a, int b) {
    return a + b;
}

Go:

func add(a int, b int) int {
    return a + b
}

In Go, function signatures include types for all parameters and the return value.

Control Structures

Most Java control structures are present in Go, but Go has some key differences:

  • No parentheses around conditions.

  • Curly braces are mandatory.

  • while is replaced by for.

Java:

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

Go:

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

Infinite loop in Go:

for {
    // loop forever
}

Packages and Imports

In Java:

import java.util.*;

In Go:

import (
    "fmt"
    "math"
)

Each .go file belongs to a package. main is the entry point.

No Exceptions β€” Use Error Returns

Go avoids try-catch for error handling.

Java:

try {
    int result = divide(4, 0);
} catch (ArithmeticException e) {
    System.out.println("Error: " + e.getMessage());
}

Go:

result, err := divide(4, 0)
if err != nil {
    fmt.Println("Error:", err)
}

Go forces you to deal with errors explicitly.

No Classes, Use Structs

Java:

class User {
    String name;
    int age;
}

Go:

type User struct {
    Name string
    Age  int
}

Methods on Structs

In Go, you define methods on structs, not on classes.

func (u User) Greet() string {
    return "Hello, " + u.Name
}

This achieves behavior similar to Java’s class methods.

No null, Use nil

Go uses nil for:

  • Pointers

  • Maps

  • Slices

  • Channels

  • Interfaces

No NullPointerException, but you must still handle nil references manually.

No Constructors, Use Factory Functions

Go does not have constructors like Java. You use simple functions to create structs.

func NewUser(name string, age int) User {
    return User{Name: name, Age: age}
}

Concurrency Made Easy


Go's concurrency model is based on goroutines and channels.

Goroutines

go fmt.Println("Running asynchronously")

Channels

ch := make(chan string)

// Send
go func() { ch <- "done" }()

// Receive
msg := <-ch
fmt.Println(msg)

This model is easier and safer than Java's Thread, Runnable, and ExecutorService.


Testing


Go has testing built in:

Test file:

// file: math_test.go
import "testing"

func TestAdd(t *testing.T) {
    if Add(2, 3) != 5 {
        t.Error("Add failed")
    }
}

Run tests:

go test ./...

Tooling: Minimal and Fast


  • go fmt β†’ Formats code

  • go vet β†’ Detects bugs

  • go run β†’ Compiles and runs

  • go build β†’ Compiles to binary

  • go mod β†’ Manages dependencies

You don’t need Maven or Gradle. The Go toolchain is self-sufficient.


Deployment Simplicity


Go compiles to a single native binary:

go build -o myapp

Just upload the binary to your server β€” no JVM, no containers (unless you want them).