Struct, methods and interfaces in Go vs Java | Types - Language

Series: Go for Java Developers — exploring struct, interface, receiver types and type embedding

In this article, we will examine how types architecture is built in Go. For a Java developer, this is especially important, as Go does not use classes in the conventional sense, and types and methods are organized differently. We will compare the Go ↔ Java approach to understand how structures, methods, and interfaces are implemented.


Struct — basic data structure in Go

Struct in Go is an analogue of a class without methods. It stores data, but behavior is added through methods.

Example of struct

// Go
type User struct {
    Name string
}

func main() {
    u := User{Name: "Alice"}
    fmt.Println(u.Name)
}

Java equivalent:

// Java
class User {
    String name;
}

public class Main {
    public static void main(String[] args) {
        User u = new User();
        u.name = "Alice";
        System.out.println(u.name);
    }
}
Struct is just a container for data. Methods are added separately. No need to inherit or create classes to store fields.

Methods and receiver types

In Go a method is bound to a type via receiver. Receiver can be a value or a pointer.

Example of a method with a value

// Go
type User struct {
    Name string
}

func (u User) Print() {
    fmt.Println(u.Name)
}

func main() {
    u := User{Name: "Alice"}
    u.Print()
}

Java equivalent:

// Java
class User {
    String name;

    void print() {
        System.out.println(name);
    }
}

public class Main {
    public static void main(String[] args) {
        User u = new User();
        u.name = "Alice";
        u.print();
    }
}

Receiver type affects behavior:

  • Value receiver — the method works with a copy
  • Pointer receiver — the method can change the original data

Pointer receiver example

// Go
func (u *User) Rename(newName string) {
    u.Name = newName
}

func main() {
    u := User{Name: "Alice"}
    u.Rename("Bob")
    fmt.Println(u.Name) // Bob
}
For Java developers: Pointer receiver is similar to passing an object by reference, Value receiver — like passing primitives or copies of objects.

Interface — implicit implementation

In Go, interfaces are implemented automatically. If a type has methods that match the interface — it implements it. No implements is needed.

Example of an interface

// Go
type Printer interface {
    Print()
}

type User struct {
    Name string
}

func (u User) Print() {
    fmt.Println(u.Name)
}

func main() {
    var p Printer = User{Name: "Alice"}
    p.Print()
}

Java equivalent:

// Java
interface Printer {
    void print();
}

class User implements Printer {
    String name;

    public void print() {
        System.out.println(name);
    }
}

public class Main {
    public static void main(String[] args) {
        Printer p = new User();
        ((User)p).name = "Alice";
        p.print();
    }
}
Go makes the interface system very flexible. You can implement an interface without explicit declaration.

Type embedding — composition instead of inheritance

Go does not use inheritance like in Java. For code reuse, embedding is used.

Example of embedding

// Go
type Person struct {
    Name string
}

func (p Person) PrintName() {
    fmt.Println(p.Name)
}

type Employee struct {
    Person // embedding
    Position string
}

func main() {
    e := Employee{Person: Person{Name: "Alice"}, Position: "Developer"}
    e.PrintName() // can be called directly
}

Java equivalent:

// Java
class Person {
    String name;

    void printName() {
        System.out.println(name);
    }
}

class Employee extends Person {
    String position;
}

public class Main {
    public static void main(String[] args) {
        Employee e = new Employee();
        e.name = "Alice";
        e.position = "Developer";
        e.printName();
    }
}
Embedding ≈ inheritance, but it is composition. Methods of the embedded type are accessible directly, but Employee and Person are different types.

Comparison of Key Concepts Go ↔ Java

Concept Go Java Comment
Class / struct struct class Struct holds data; methods are bound separately
Methods receiver (value / pointer) regular class methods Pointer receiver allows modifying data
Interface implicitly implemented implements Go is more flexible, no explicit declaration
Inheritance type embedding extends Go uses composition instead of inheritance

Practical Output

For a Java developer transitioning to Go, it is important to remember:

  • Struct = data container without behavior
  • Methods are bound through receiver (value/pointer)
  • Interfaces are implemented automatically
  • Embedding replaces inheritance, but this is composition
  • The Go type system is simple, flexible, and safe

These principles allow building Go architecture that is understandable and convenient for large projects, without the unnecessary complexity inherent to Java classes.


🌐 На русском
Total Likes:0

Оставить комментарий

My social media channel
By sending an email, you agree to the terms of the privacy policy

Useful Articles:

Go ↔ Java: Complete Guide to Runtime, Memory, and Allocator - Part 3
This article is a comprehensive guide to the key aspects of memory and runtime work in Go and Java. We will discuss fundamental concepts: execution scheduler, memory barriers, memory alignment, stack ...
Loops in Java: for, while, do while, continue and break statements
Hello! This is Vitaly Lesnykh. Today we will continue the course “Java Basics for Beginners” and discuss one of the most important topics in programming — loops. A loop is the repetition of code exe...
Arithmetic operators
In this lesson, we will talk about arithmetic operations and operators. In programming, operators are commands that perform specific actions: mathematical, string, logical, or comparison operations. T...

New Articles:

Concurrency is not about “starting many threads”. It’s about agreements between them. Imagine a restaurant kitchen: — cooks (threads / goroutines) — orders (tasks) — and the main question: how do th...
When HashMap starts killing production: the engineering story of ConcurrentHashMap
Imagine a typical production service. 32 CPU hundreds of threads configuration / session / rate limits cache tens of thousands of operations per second And somewhere inside — a regular Map. At first...
Zero Allocation in Java: what it is and why it matters
Zero Allocation — is an approach to writing code in which no unnecessary objects are created in heap memory during runtime. The main idea: fewer objects → less GC → higher stability and performance. ...
Fullscreen image