Go is not your typical object-oriented programming (OOP) language. It doesn’t have classes, but don’t let that fool you—Go still lets you achieve OOP principles like encapsulation, inheritance (kind of), and polymorphism, just in a different way! Let’s break it down, without the drama.
No Classes? No Problem!
In Go, we don’t have classes, but we have structs. Think of them as blueprints for objects, just without the extra baggage.
package main
import "fmt"
type Animal struct {
Name string
Sound string
}
func main() {
dog := Animal{Name: "Dog", Sound: "Woof!"}
fmt.Println(dog.Name, "says", dog.Sound)
}
This is like creating an object in a class-based language, just with fewer complications!
Encapsulation - Keeping Secrets Like a Spy
Go achieves encapsulation through exported (uppercase) and unexported (lowercase) identifiers. If a field starts with an uppercase letter, it’s public; if it’s lowercase, it’s private (restricted to the same package).
package main
import "fmt"
type secretAgent struct {
codeName string // private (unexported)
Weapon string // public (exported)
}
func main() {
agent := secretAgent{codeName: "007", Weapon: "Silenced Pistol"}
fmt.Println("Agent’s weapon:", agent.Weapon)
// fmt.Println(agent.codeName) // This will cause an error!
}
In this case, codeName
is private and can’t be accessed outside the package! James Bond approves. 🍸
Inheritance? Not Quite, But We Have Composition!
Instead of inheritance, Go uses struct embedding, which is often better because it avoids the mess of deep inheritance trees.
package main
import "fmt"
type Animal struct {
Name string
}
type Dog struct {
Animal
Breed string
}
func main() {
myDog := Dog{Animal: Animal{Name: "Buddy"}, Breed: "Golden Retriever"}
fmt.Println(myDog.Name, "is a", myDog.Breed)
}
Here, Dog
gets everything from Animal
without the baggage of classical inheritance. Simple and clean!
4. Polymorphism - The Art of Shape-Shifting
Polymorphism in Go is achieved using interfaces. If it walks like a duck and quacks like a duck, it’s a duck!
package main
import "fmt"
type Speaker interface {
Speak()
}
type Dog struct {}
type Cat struct {}
func (d Dog) Speak() {
fmt.Println("Woof!")
}
func (c Cat) Speak() {
fmt.Println("Meow!")
}
func makeItSpeak(s Speaker) {
s.Speak()
}
func main() {
dog := Dog{}
cat := Cat{}
makeItSpeak(dog)
makeItSpeak(cat)
}
Different types implement the Speak()
method, and Go treats them all as Speaker
. Magic? No, just Go!
Why Go's OOP is Different (And Why You’ll Love It)
- No tangled class hierarchies – Just use structs and interfaces!
- Composition over inheritance – More flexible, less messy.
- Encapsulation through package-level visibility – Keep secrets safe.
- Polymorphism through interfaces – Keep things simple and scalable.
Go doesn’t follow traditional OOP, but that’s actually a good thing! With structs, interfaces, and composition, you get all the benefits of OOP without the complexity.
0 Comments