Advanced Structs

Back

Loading concept...

🏗️ Advanced Structs in Go: Building Amazing LEGO Castles!

Imagine you have a big box of LEGO bricks. You can build simple things like a small house. But what if you want to build a magical castle with towers, rooms inside rooms, and secret compartments? That’s what Advanced Structs let you do in Go!


🎯 What We’ll Learn

Think of structs like LEGO buildings. Today we’ll learn:

  • Nested Structs → Rooms inside rooms
  • Anonymous Fields → Bricks without name tags
  • Struct Embedding → Getting superpowers from other buildings
  • Struct Comparison → “Are these two castles the same?”
  • Struct Tags → Secret sticky notes on your bricks

🏠 Nested Structs: Rooms Inside Rooms

The Story

Imagine you’re building a dollhouse. Inside the dollhouse, there’s a bedroom. The bedroom has a bed. The bed has a pillow!

That’s nesting — putting one thing inside another, inside another!

What It Looks Like

type Pillow struct {
    Color string
    Soft  bool
}

type Bed struct {
    Size   string
    Pillow Pillow  // A pillow inside the bed!
}

type Bedroom struct {
    Name string
    Bed  Bed  // A bed inside the bedroom!
}

Real Example

myRoom := Bedroom{
    Name: "Cozy Corner",
    Bed: Bed{
        Size: "Twin",
        Pillow: Pillow{
            Color: "Blue",
            Soft:  true,
        },
    },
}

// Getting to the pillow color:
fmt.Println(myRoom.Bed.Pillow.Color)
// Output: Blue

🎨 Picture This

graph TD A["Bedroom"] --> B["Bed"] B --> C["Pillow"] A --> D["Name: Cozy Corner"] B --> E["Size: Twin"] C --> F["Color: Blue"] C --> G["Soft: true"]

Why It’s Awesome

  • Organized → Everything has its place
  • Clear → You know exactly where things are
  • Real World → Most things ARE nested (your city has neighborhoods, neighborhoods have houses, houses have rooms!)

đź‘» Anonymous Fields: The Invisible Name Tags

The Story

When you get a birthday present, it usually has a tag saying “From: Grandma.” But what if Grandma just handed you the present directly? You’d still know it’s a present — it just doesn’t have a name tag!

What It Means

Instead of giving a field a name AND a type, you just give it a type. Go uses the type name as the field name automatically!

Normal Way vs Anonymous Way

// Normal way (with name tag)
type Pet struct {
    AnimalType string
}

// Anonymous way (no name tag!)
type Pet struct {
    string  // This field is named "string"
}

Better Real Example

type Person struct {
    string  // Name (anonymous)
    int     // Age (anonymous)
}

p := Person{"Alice", 10}

// Access using type name:
fmt.Println(p.string)  // Alice
fmt.Println(p.int)     // 10

More Useful: Anonymous Struct Types

type Address struct {
    City    string
    Country string
}

type Employee struct {
    Name    string
    Address  // Anonymous! No field name given
}

emp := Employee{
    Name: "Bob",
    Address: Address{
        City:    "Tokyo",
        Country: "Japan",
    },
}

// Magic! Access directly:
fmt.Println(emp.City)  // Tokyo (not emp.Address.City!)

🌟 The Magic

With anonymous fields, you can access inner fields directly without typing the middle name. It’s like a shortcut!


🦸 Struct Embedding: Getting Superpowers!

The Story

Imagine you’re a regular kid. Then you put on a superhero cape, and suddenly you can FLY! You didn’t learn to fly — the cape gave you that power.

Struct embedding is like wearing that cape. Your struct gets all the abilities of another struct automatically!

How It Works

// The "cape" with superpowers
type Flyer struct {
    MaxSpeed int
}

func (f Flyer) Fly() {
    fmt.Println("Zooming at", f.MaxSpeed, "mph!")
}

// Regular person puts on the cape
type Hero struct {
    Name  string
    Flyer // Embedded! Gets flying powers!
}

Using the Powers

superman := Hero{
    Name:  "Clark",
    Flyer: Flyer{MaxSpeed: 1000},
}

// Superman can fly! (method promoted)
superman.Fly()  // "Zooming at 1000 mph!"

// Can also access MaxSpeed directly
fmt.Println(superman.MaxSpeed)  // 1000

🎨 Picture This

graph TD A["Hero"] -->|embeds| B["Flyer"] A --> C["Name: Clark"] B --> D["MaxSpeed: 1000"] B --> E["Fly method"] A -.->|can use| E

Embedding vs Nested: What’s Different?

Feature Nested Embedded
Access fields hero.Flyer.MaxSpeed hero.MaxSpeed
Use methods hero.Flyer.Fly() hero.Fly()
Feels like Has a thing IS that thing

Multiple Embeddings (More Capes!)

type Swimmer struct{}
func (s Swimmer) Swim() {
    fmt.Println("Splash!")
}

type Aquaman struct {
    Name string
    Flyer
    Swimmer
}

// Aquaman can do BOTH!
aquaman := Aquaman{Name: "Arthur"}
aquaman.Fly()   // Works!
aquaman.Swim()  // Works!

⚖️ Struct Comparison: Are They Twins?

The Story

You have two toy cars. They look the same — same color, same size, same wheels. Are they the same car? Well, they’re equal (identical twins), even if they’re not the exact same object.

The Rule

Go lets you compare structs with == ONLY IF all the fields inside can be compared too!

Comparable Structs

type Point struct {
    X int
    Y int
}

p1 := Point{X: 5, Y: 10}
p2 := Point{X: 5, Y: 10}
p3 := Point{X: 1, Y: 1}

fmt.Println(p1 == p2)  // true (same values!)
fmt.Println(p1 == p3)  // false (different values)

đźš« NOT Comparable: Slices, Maps, Functions

type Bag struct {
    Items []string  // Slice inside!
}

b1 := Bag{Items: []string{"toy"}}
b2 := Bag{Items: []string{"toy"}}

// b1 == b2  ❌ WON'T COMPILE!
// Error: slice can only be compared to nil

Quick Reference

Can Compare? Types
âś… Yes int, string, bool, arrays, structs (if all fields comparable)
❌ No slices, maps, functions

Pro Tip: Use reflect.DeepEqual for Complex Stuff

import "reflect"

b1 := Bag{Items: []string{"toy"}}
b2 := Bag{Items: []string{"toy"}}

fmt.Println(reflect.DeepEqual(b1, b2))  // true

🏷️ Struct Tags: Secret Sticky Notes

The Story

Imagine you’re packing boxes for a move. You write on each box: “FRAGILE” or “BOOKS” or “KITCHEN.” These notes help the movers know what to do with each box.

Struct tags are like those sticky notes! They’re extra information attached to fields that other programs can read.

What They Look Like

type User struct {
    Name  string `json:"name"`
    Email string `json:"email_address"`
    Age   int    `json:"age,omitempty"`
}

See those backtick strings after each field? Those are tags!

How Tags Help

1. JSON Conversion

user := User{
    Name:  "Luna",
    Email: "luna@stars.com",
    Age:   0,
}

data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Luna","email_address":"luna@stars.com"}
// Notice: Age is missing (omitempty + zero value)

2. Database Mapping

type Product struct {
    ID    int    `db:"product_id"`
    Title string `db:"product_title"`
}

3. Form Validation

type Form struct {
    Email string `validate:"required,email"`
    Age   int    `validate:"min=0,max=120"`
}

Tag Anatomy

`key1:"value1" key2:"value2,option"`
  • Backticks → Required wrapper
  • key → Who reads this (json, db, validate)
  • value → What they should know
  • Multiple tags → Space-separated

Reading Tags (Behind the Scenes)

import "reflect"

type Hero struct {
    Name string `json:"hero_name" xml:"name"`
}

t := reflect.TypeOf(Hero{})
field, _ := t.FieldByName("Name")

fmt.Println(field.Tag.Get("json"))  // hero_name
fmt.Println(field.Tag.Get("xml"))   // name

Common Tag Patterns

Tag Purpose Example
json JSON encoding json:"userName"
xml XML encoding xml:"user-name"
db Database column db:"user_name"
validate Validation rules validate:"required"
yaml YAML encoding yaml:"user_name"

🎮 Putting It All Together

Here’s a complete example using EVERYTHING we learned:

type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
}

type ContactInfo struct {
    Email string `json:"email"`
    Phone string `json:"phone,omitempty"`
}

type Person struct {
    Name        string `json:"name"`
    Age         int    `json:"age"`
    Address            // Embedded!
    ContactInfo        // Embedded!
}

func main() {
    p := Person{
        Name: "Zara",
        Age:  12,
        Address: Address{
            Street: "123 Fun Lane",
            City:   "Playville",
        },
        ContactInfo: ContactInfo{
            Email: "zara@play.com",
        },
    }

    // Direct access (thanks to embedding!)
    fmt.Println(p.City)   // Playville
    fmt.Println(p.Email)  // zara@play.com

    // JSON output uses our tags
    data, _ := json.Marshal(p)
    fmt.Println(string(data))
}

🌟 Remember These Magic Words

Concept One-Line Summary
Nested Structs Boxes inside boxes — organize your data!
Anonymous Fields No name tag needed — use type as name
Struct Embedding Get superpowers from other structs
Struct Comparison == works if all fields are comparable
Struct Tags Sticky notes that help other programs

🚀 You Did It!

You just learned how to build complex, powerful data structures in Go!

Think of it this way:

  • You started with simple LEGO bricks (basic structs)
  • Now you can build castles with rooms inside rooms
  • Add invisible shortcuts with anonymous fields
  • Give your creations superpowers through embedding
  • Check if two creations are twins
  • And leave secret notes for other programs to read!

Go forth and build amazing things! 🏰✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.