Generic Types

Back

Loading concept...

🎁 Go Generics: Magic Boxes That Fit Anything!

The Story of the Magic Toy Box

Imagine you have a magic toy box. This isn’t an ordinary box. It can hold ANY toy you want — cars, dolls, dinosaurs, or even robot action figures. But here’s the cool part: once you tell the box what kind of toy it’s holding, it ONLY gives you that type back!

That’s exactly what Generics are in Go. They let you create flexible containers and tools that work with ANY type, while keeping everything safe and organized.


🧱 Generic Structs: Building Your Magic Box

What’s a Generic Struct?

Think of a struct like a container that holds information. A generic struct is a container that can hold different types of things — you decide what type when you use it!

Simple Example: A Box for Anything

// T is like a label that says
// "put any type here"
type Box[T any] struct {
    Item T
}

What’s happening here?

  • Box is our container name
  • [T any] means “T can be any type”
  • Item T means the box holds one item of type T

Using Your Magic Box

// A box for numbers
numberBox := Box[int]{Item: 42}

// A box for words
wordBox := Box[string]{Item: "Hello!"}

// A box for true/false values
boolBox := Box[bool]{Item: true}

See? Same box design, different contents!

Real-Life Example: A Pair Holder

Sometimes you want to keep two things together:

type Pair[T any, U any] struct {
    First  T
    Second U
}

// Name and Age pair
person := Pair[string, int]{
    First:  "Maya",
    Second: 8,
}

// Two coordinates
point := Pair[float64, float64]{
    First:  3.5,
    Second: 7.2,
}

🔌 Generic Interfaces: The Universal Remote

What’s a Generic Interface?

Imagine a universal remote that works with ANY TV brand. You don’t need separate remotes for Sony, Samsung, or LG. One remote, many TVs!

A generic interface is like that remote. It defines WHAT something can do, without caring about the specific type.

Simple Example: A Storer

type Storer[T any] interface {
    Store(item T)
    Get() T
}

What’s happening?

  • Any type that has Store and Get methods fits this interface
  • T is the type of item being stored

Building Something That Fits

// Memory stores items in... well, memory!
type Memory[T any] struct {
    data T
}

func (m *Memory[T]) Store(item T) {
    m.data = item
}

func (m *Memory[T]) Get() T {
    return m.data
}

Using the Universal Interface

// Memory fits the Storer interface!
var storage Storer[string] = &Memory[string]{}
storage.Store("Secret message")
msg := storage.Get()
// msg is "Secret message"

Why This Is Awesome

You can write code that works with ANY Storer without knowing what’s inside:

func SaveAndLoad[T any](s Storer[T], item T) T {
    s.Store(item)
    return s.Get()
}

🧙 Type Inference: Go Reads Your Mind!

What Is Type Inference?

Here’s the magic trick: Go is smart enough to figure out what type you mean, so you don’t always have to spell it out!

It’s like when you show your mom a crayon and say “Can you get me more of these?” She doesn’t need you to say “red crayon” — she can SEE it’s red!

Example: Go Guesses the Type

Without inference (you tell Go everything):

numbers := Box[int]{Item: 100}

With inference (Go figures it out):

// Go sees 100 is an int, so Box must be Box[int]
numbers := Box{Item: 100}  // Error! Structs need explicit types

Wait! Struct instantiation usually needs explicit types. But functions can infer!

Functions Love to Infer

func Wrap[T any](item T) Box[T] {
    return Box[T]{Item: item}
}

// You could write:
box1 := Wrap[string]("Hello")

// But Go can infer from the argument:
box2 := Wrap("Hello")  // Go knows T = string!

More Inference Magic

func First[T any](items []T) T {
    return items[0]
}

// Go sees []int, so T must be int
nums := []int{10, 20, 30}
first := First(nums)  // No [int] needed!

// Go sees []string, so T must be string
words := []string{"Go", "is", "fun"}
word := First(words)  // No [string] needed!

When Inference Works Best

Situation Inference? Example
Function with typed arguments ✅ Yes! First(nums)
Empty or ambiguous arguments ❌ No Make[int]()
Struct creation ❌ Usually No Box[int]{...}
Variable declarations ✅ Sometimes x := 5

🎨 Putting It All Together

Let’s build a mini-warehouse using everything we learned!

// Generic struct: holds any item
type Warehouse[T any] struct {
    items []T
}

// Generic interface: what a warehouse does
type Storage[T any] interface {
    Add(item T)
    GetAll() []T
}

// Warehouse implements Storage
func (w *Warehouse[T]) Add(item T) {
    w.items = append(w.items, item)
}

func (w *Warehouse[T]) GetAll() []T {
    return w.items
}

// Generic function with inference
func AddMany[T any](s Storage[T], items ...T) {
    for _, item := range items {
        s.Add(item)
    }
}

Using Our Warehouse

// Create a warehouse for toys (strings)
toys := &Warehouse[string]{}

// Type inference at work!
AddMany(toys, "Car", "Robot", "Dinosaur")

// Get all toys back
allToys := toys.GetAll()
// ["Car", "Robot", "Dinosaur"]

🌟 Quick Summary

graph TD A["Generics in Go"] --> B["Generic Structs"] A --> C["Generic Interfaces"] A --> D["Type Inference"] B --> B1["Box[T any]"] B --> B2["Pair[T, U]"] C --> C1["Storer[T]"] C --> C2["Any type that fits"] D --> D1["Go guesses types"] D --> D2["Less typing for you!"]

Remember:

  • Generic Structs = Magic boxes that hold any type you choose
  • Generic Interfaces = Universal remotes that work with anything
  • Type Inference = Go reading your mind so you type less

🚀 You Did It!

Now you understand Go Generics! You can:

✅ Create structs that work with ANY type ✅ Define interfaces that accept ANY type ✅ Let Go figure out types automatically

Generics make your code flexible, reusable, and still safe. It’s like having a toolbox where every tool adjusts to fit whatever you need!

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.