Аккаунт Войти / Регистрация
Тема
Размер текста
Struct, methods and interfaces in Go vs Java | Types - Language

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.

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

Мой канал в социальных сетях
Отправляя email, вы принимаете условия политики конфиденциальности

Полезные статьи:

Welcome to my IT blog, my name is Vitaly Lesnykh. I ve been in IT since 2004: I created my first website as a thesis in college, and I ve been developing apps and websites since then. I ve worked as …
Low-level mechanisms - part 2 | Go ↔ Java
In this article, we gathered the key low-level mechanisms of Go that most often raise questions for developers coming from Java. We will consider: unsafe.Pointer, struct alignment, pointer arithmetic,…
Scheduler internals in Go ↔ Java: how your code is actually executed
When you write go func() or create a Thread in Java, it seems like you are managing concurrency. But in reality, you are passing the task to the scheduler. And this is where the real show begins. Go…

Новые статьи:

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. …