Lab 05: Interfaces & Polymorphism

Time: 30 minutes | Level: Practitioner | Docker: docker run -it --rm golang:1.22-alpine sh

Overview

Interfaces in Go are implicitly satisfied — a type implements an interface simply by having the right methods. No implements keyword. This structural typing enables powerful polymorphism and decoupled design.

Step 1: Interface Definition & Implicit Implementation

package main

import (
    "fmt"
    "math"
)

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64      { return math.Pi * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius }

type Rect struct{ W, H float64 }
func (r Rect) Area() float64      { return r.W * r.H }
func (r Rect) Perimeter() float64 { return 2 * (r.W + r.H) }

// Works with any Shape — polymorphism!
func printShape(s Shape) {
    fmt.Printf("Area=%.2f  Perimeter=%.2f\n", s.Area(), s.Perimeter())
}

func main() {
    shapes := []Shape{
        Circle{Radius: 5},
        Rect{W: 4, H: 6},
    }
    for _, s := range shapes {
        printShape(s)
    }
}

💡 Tip: Keep interfaces small. The standard library's io.Reader has one method — and it's one of the most powerful abstractions in Go.

Step 2: Interface Composition

Interfaces can embed other interfaces.

Step 3: Empty Interface — any

any (alias for interface{}) accepts values of any type.

💡 Tip: Prefer concrete types or typed interfaces over any. any loses type safety — use type assertions or switches to recover it.

Step 4: Type Assertion

Extract a concrete type from an interface value.

Step 5: Type Switch

Dispatch on the runtime type of an interface value.

Step 6: fmt.Stringer and io.Reader / io.Writer

Implementing standard library interfaces makes your types work with existing ecosystem code.

Step 7: Interface Pitfalls — nil Interface vs nil Pointer

💡 Tip: Never return a typed nil as an error. Return nil directly.

Step 8: Capstone — Plugin System via Interfaces

📸 Verified Output:

Summary

Concept
Key Points

Implicit implementation

No implements — method set matching

Interface composition

Embed interfaces to build larger contracts

any / interface{}

Accept any type; use type switch to inspect

Type assertion v.(T)

Extract concrete type; use comma-ok form

Type switch

Multi-way dispatch on runtime type

fmt.Stringer

String() string — auto-used by fmt

io.Reader/Writer

Foundation of Go's I/O model

nil interface pitfall

Return nil, not typed nil pointer

Last updated