Extending a Struct in Go

Extending a Struct in Go

In object-oriented programming, we can extend classes in order to re-use a lot of existing code.

For this extension, Go doesn't allow us to inherit from the types - instead we're extending the existing struct via composition.

This allows us to use all of the same properties and functions of the original struct.

I've found this to be especially useful when encoding and decoding JSON. As the standard library encoding/json correctly decodes into the extended struct.

package main

import (
    "fmt"
)

type Greeting struct {
    FirstName string
}

func (g Greeting) GetName() string {
    return g.FirstName
}

func (g Greeting) OldPrint() {
    fmt.Printf("Hello, %s\n", g.GetName())
}

// --- Extend Greeting Struct ---
type ExtendedGreeting struct {
    Greeting
    LastName string
}

// ---

func (ext ExtendedGreeting) GetName() string {
    return fmt.Sprintf("%s %s", ext.FirstName, ext.LastName)
}

func (ext ExtendedGreeting) NewPrint() {
    fmt.Printf("Hello, %s\n", ext.GetName())
}

func main() {
    greeting := Greeting{FirstName: "John"}
    extended := ExtendedGreeting{Greeting: greeting, LastName: "Snow"}

    extended.OldPrint()             // "Hello, John"
    extended.NewPrint()             // "Hello, John Snow"
    fmt.Println(extended.FirstName) // "John"
}

Gotchas

One thing to note is that functions that expect the old struct will bypass any overridden functions that you have written. Take a look at how extended.OldPrint() still calls Greeting#GetName() even though ExtendedGreeting#GetName() exists.

Storing Files in S3 with Go

Storing Files in S3 with Go

The Business Case for Snowplow Analytics

The Business Case for Snowplow Analytics