OOPs in Go — The Simple Way

OOPs in Go — The Simple Way

Go isn’t our typical object-oriented language like java, c++, python — and that’s by design. It focuses on simplicity, clarity, and minimalism. But it still supports the OOPs principle — just in its own way.

Most of us might have studied objects in our early programming days — something that has state (data) and can perform actions (behavior). And classes are simply the blueprint used to create those objects.

In Go, instead of classes. We use structs to mimic that behavior

🔧 Structs in Go — The OOPs Building Block

Go doesn’t use classes like other OOP languages. Instead, it uses structs — the same concept you may have seen in C or C++. But in Go, structs are more powerful. You can attach methods (method receivers) to them. That means your struct isn’t just a data holder — it can define behavior too! 

// Animal struct
type Animal struct {
    Name    string
    Age     int
    Habitat string
}

/* we dont have by default constrcutor, but we can define one using regular method */
func NewAnimal(name string, age int, habitat string) *Animal {
    return &Animal{
        Name:    name,
        Age:     age,
        Habitat: habitat,
    }
}        

Go removes the clutter of OOP by skipping constructors, destructors, and even traditional access modifiers. Instead, Go prefers composition over inheritance — which means we build things by combining smaller parts instead of relying on rigid parent-child relationships. 

Now, let’s discuss each principle of OOPs with code snippets in detail. I've also implemented the whole example trying to cover basics , please check this out Zoo management System 


Encapsulation — Who can touch my data?

Let’s first understand what “encapsulation” really means. 

Imagine a doctor encapsulates bitter medicine inside a pill. You swallow the pill without tasting the bitterness. In programming, it’s the same idea — we wrap up complex things so users only see what they need.  This helps us to keeps things simple.

Here’s why we Encapsulate code

  1. To Protect Sensitive Data : prevents accidental or unauthorized changes, ensuring data integrity and security by controlling the access of data.
  2. To Make Code Easier to Use : We dont need to understand the whole class to access some attribute, getter and setter make it more easier to use it.
  3. For Safety and Control : gives the developer full control over how data is accessed and modified.

How Go Implements Encapsulation 

Now here’s the cool part — Go keeps it extremely simple. Instead of keywords like private or public, it just uses capitalization

  • Capitalized names (e.g., Animal in above eg. ) are exported — they can be used outside the package (like public). 
  • Lowercase names (e.g., name, age, habitat) are unexported — they’re private to the package.



Abstraction — What do I want to expose?

Abstraction - showing the only important stuff, hiding the rest,

for eg. when we press brakes while driving a car, we dont care how the breaks are mechanically working. That’s abstraction: You use something without needing to know its inner details.

Why Do We Need Abstraction?

  1. To Hide the Unnecessary Complexity : helps users to focus on what something does, not how it does.
  2. To Make Code Easier to Use : provides a clean and minimal interface to interact with complext systems,
  3. Increase Flexibility and Maintainability : makes codes more adaptable and testable

How is Abstraction Done in Go?

Go does'nt use the traditionals abstract classes - instead, it provides the interfaces.

// defining an inteface( function name only, no implementation) 
type Animal interface{
       Speak() string 
}

// we dont use a keyword to impelement interface, just implement all function
type Dog struct{}
func(d Dog) Speak() string{
  return "woof woof"
}        

Similarly, we can create other types with their own implementation of Speak() function


Inheritance (Is-A) , Via Composition (Has-A)

In traditional OOP, inheritance means creating a new new class that automatically gets properties and behaviour from the parent class. I

But, go does'nt support inheritance (due to tight coupling of code). Instead it promotes, Composition - building complex types, by emebding the smaller and reusable types

Why We Use Composition

  1. Code Reusability : share common functionality accross multiple types
  2. No Tight Coupling : you dont use the rigid class hierarchy
  3. Flexible Designs : you can easily extend, mix behaviours of multiple types.

How to Use Compostion

Unlinke the traditional OOP, we dont use extend here. We just embed the parent type .

type Entity struct {
    ID   int
    Name string
}

type Product struct {
    Entity      // embedded struct
    Price float64
}        

Polymorphism — Many Forms

In simple terms one interface, many implementations.

it allows different types to be treated as the same interface, even though they may have different implementations. In other words, If multiple structs implement the same interface, you can write code that works on the interface — not the specific struct —and it will work with any type that follows that behavior.

// common interface 
type Notifier interface {
    Notify(message string)
}


// multiple types implementing the same interface 
type EmailNotifier struct{}
func (e EmailNotifier) Notify(message string) {
    fmt.Println("Sending Email:", message)
}

type SMSNotifier struct{}
func (s SMSNotifier) Notify(message string) {
    fmt.Println("Sending SMS:", message)
}

// using polymorphism
func SendAlert(n Notifier) {
    n.Notify("System Down!")
}
// calling same function for different types 
func main() {
    var n Notifier
    n = EmailNotifier{}
    SendAlert(n) // Sending Email: System Down!
    n = SMSNotifier{}
    SendAlert(n) //  Sending SMS: System Down!
}        
Benefits of Using Polymorphism

  1. Code Reusability : You can write a function once and use it for multiple types.
  2. Scalability and Extensibility : You can add new features (types) without changing existing code.
  3. Flexibility and Loose Coupling : Your code works with interface types, not concrete types.

Mohd Suhail

Software Developer | ReactJs | NodeJS | React Native

1mo

I'm happy to join

To view or add a comment, sign in

Explore topics