Monday, February 9, 2026

Interfaces

    Profile Pic of Akash AmanAkash Aman

    Updated: February 2026

    Interfaces

    The Interface Definition

    Concept: A type that specifies a set of method signatures. It defines what an object can do, rather than what it is.

    • Behavior: Unlike structs (which hold state/data), interfaces hold contracts. Any type that implements all methods in an interface is said to satisfy that interface.
    • Why: This allows for Polymorphism. You can write a single function that works with any type, as long as that type has the required methods.
    go
    // The Contract
    type Shape interface {
        Area() float64
        Perimeter() float64
    }
    

    Implicit Implementation (The "Duck Typing" of Go)

    Concept: In Go, you do not use an implements keyword. A type satisfies an interface automatically by having the required methods.

    • Behavior: This is "decoupled" design. A developer can create a struct in one package, and a user can create an interface in another package to "wrap" that struct without the original developer ever knowing about it.
    • Why: It reduces boilerplate and makes code incredibly flexible. If it walks like a duck and quacks like a duck, Go treats it as a duck.
    go
    type Circle struct {
        Radius float64
    }
    
    // Circle implements Shape automatically because it has these methods
    func (c Circle) Area() float64 {
        return 3.14 * c.Radius * c.Radius
    }
    
    func (c Circle) Perimeter() float64 {
        return 2 * 3.14 * c.Radius
    }
    

    The Empty Interface (interface{} or any)

    Concept: An interface that has zero methods.

    • Behavior: Since every type has at least zero methods, every type satisfies the empty interface. In Go 1.18+, the keyword any was introduced as an alias for interface{}.
    • Why: Used when you don't know the type of data beforehand (like fmt.Println which accepts anything). However, it should be used sparingly as it bypasses Go's type safety.

    Interface Values & Dynamic Dispatch

    Concept: Under the hood, an interface value is a small tuple of two pointers: one to the concrete type information and one to the actual data.

    • Behavior: When you call a method on an interface, Go uses these pointers to find the right method to run at runtime.
    • Why: This is how Go remains a statically typed language while behaving dynamically. It knows exactly what the underlying "thing" is, even if it's hiding behind an interface.
    go
    var s Shape = Circle{Radius: 5}
    // Under the hood: ( {Radius: 5}, main.Circle )
    

    Composition & Advanced Patterns

    Interface Embedding (Composition)

    Concept: Combining multiple interfaces into a larger one.

    Setup:

    • Interface Structure
    go
    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    
    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    
    // Embedding: ReadWriter has the methods of both Reader and Writer
    type ReadWriter interface {
        Reader
        Writer
    }
    
    • Why: It promotes the Interface Segregation Principle. You can define small, focused interfaces and compose them into bigger ones only when needed. It keeps your code clean and reusable.

    Type Assertions & Switches

    Concept: A way to "extract" the underlying concrete type from an interface.

    • Behavior: You can ask the interface: "Are you actually a Circle?"
    go
    var s Shape = Circle{Radius: 5}
    
    // Type Assertion
    c, ok := s.(Circle)
    if ok {
        fmt.Println(c.Radius)
    }
    
    // Type Switch
    switch v := s.(type) {
    case Circle:
        fmt.Printf("It's a circle with radius %f\n", v.Radius)
    case Square:
        fmt.Println("It's a square!")
    }
    
    • Why: This allows you to regain access to specific fields of a struct (like Radius) that are hidden when the struct is being treated as a general interface.

    Reference Guides

    Implementation Rules

    RuleExplanationResult
    Value vs PointerMethods can be defined on T or *T.Affects which types satisfy the interface.
    Nil InterfacesAn interface with no type and no value is nil.Calling a method on a nil interface causes a panic.
    Small is BetterGo convention favors 1-2 method interfaces (e.g., io.Reader).Makes the interface easier to implement and reuse.

    Summary Table

    ConceptPurposeDeveloper Impact
    ImplicitDecouplingYou don't need to declare dependencies upfront.
    anyFlexibilityAllows functions to handle unknown types.
    EmbeddingCompositionBuild complex behaviors from simple parts.
    AssertionsRecoverySafe way to convert interfaces back to concrete types.

    © 2026 Akash Aman | All rights reserved