Lesson 4 • Intermediate
Structs and Interfaces 🐹
Group data with structs, write flexible code with interfaces, and understand Go's composition-over-inheritance philosophy.
What You'll Learn in This Lesson
- • Defining structs with fields and struct tags
- • Composition with embedded structs
- • Interfaces and implicit satisfaction
- • Type assertions and type switches
- • Pointers and memory addresses
Fly() method.1️⃣ Structs
Structs are Go's way to group related data together. Unlike classes in OOP languages, structs don't support inheritance — Go uses composition (embedding) instead. Struct tags control JSON/DB serialization.
Try It: Structs
Define structs, embed them, and use struct tags
// Structs — Custom Data Types
console.log("=== Defining Structs ===");
console.log();
console.log("type User struct {");
console.log(" ID int");
console.log(" Name string");
console.log(" Email string");
console.log(" IsActive bool");
console.log("}");
console.log();
// Simulate
const user = { ID: 1, Name: "Alice", Email: "alice@dev.com", IsActive: true };
console.log("// Creating instances:");
console.log('u1 := User{ID: 1, Name: "Alice", Email: "alice@dev.com", IsAct
...2️⃣ Interfaces
Go interfaces are implicitly satisfied — no implements keyword. If a type has the right methods, it automatically satisfies the interface. This enables powerful polymorphism without tight coupling.
Try It: Interfaces
Define interfaces and see implicit satisfaction
// Interfaces — Implicit Satisfaction
console.log("=== What Are Interfaces? ===");
console.log("An interface defines a set of method signatures.");
console.log("Any type that implements those methods satisfies the interface.");
console.log("No 'implements' keyword needed — it's IMPLICIT!");
console.log();
console.log("type Shape interface {");
console.log(" Area() float64");
console.log(" Perimeter() float64");
console.log("}");
console.log();
// Simulate with objects
const circle = {
...3️⃣ Interface Composition & Type Assertions
Compose small interfaces into larger ones. Use type assertions to extract the concrete type from an interface value, and type switches for polymorphic behavior.
Try It: Composition
Compose interfaces and use type assertions
// Interface Composition & Type Assertions
console.log("=== Composing Interfaces ===");
console.log();
console.log("type Reader interface {");
console.log(" Read(p []byte) (n int, err error)");
console.log("}");
console.log();
console.log("type Writer interface {");
console.log(" Write(p []byte) (n int, err error)");
console.log("}");
console.log();
console.log("type ReadWriter interface {");
console.log(" Reader // Embeds Reader");
console.log(" Writer // Embeds Writer");
cons
...4️⃣ Pointers
Pointers hold memory addresses. Use them to modify values inside functions and avoid copying large structs. Go auto-dereferences struct pointers and forbids pointer arithmetic — keeping things safe.
Try It: Pointers
Memory addresses, dereferencing, and pointer safety
// Pointers in Go
console.log("=== Pointers — Memory Addresses ===");
console.log();
console.log(" x := 42");
console.log(" p := &x // p is a pointer to x");
console.log(" fmt.Println(*p) // 42 — dereference to get value");
console.log(" *p = 100 // Modify through pointer");
console.log(" fmt.Println(x) // 100 — x is changed!");
console.log();
let x = 42;
console.log(" x =", x);
console.log(" p := &x");
console.log(" *p = 100");
x = 100;
console.log(" x =", x, "(modifie
...⚠️ Common Mistakes
📋 Quick Reference
| Pattern | Go Syntax |
|---|---|
| Struct | type User struct { Name string } |
| Interface | type Stringer interface { String() string } |
| Embedding | type Admin struct { User } |
| Type assert | v, ok := i.(Type) |
| Pointer | p := &x; *p = 10 |
🎉 Lesson Complete!
You understand structs, interfaces, and pointers — Go's core building blocks. Next, we'll unlock Go's superpower: concurrency with goroutines!
Sign up for free to track which lessons you've completed and get learning reminders.