Advanced Datatypes

Structs

🙋 Need help? Ask an expert now!

Working with Structured Data

So far we've covered the range of 'built-in' data types, however, the most powerful data types are the ones that you create! Go offers the type Name struct {} syntax for creating your own structs that work a lot like classes in Java/C++.

Note: is Go Object-oriented?

Sort of. Throughout the sections on structs, interfaces, and methods, you will find that Go offers what is in essence a 'lightweight' object-oriented programming paradigm, coupled with many functional programming features, such as the ability to pass functions around like variables. Since Go doesn't really support 'type hierarchy' (aside from embedding, covered below) most users will find that Go is a most 'lean' implementation of core OOP.

Structs

package main

import (
    "fmt"
)

// Warning: Boring obligatory OOP-ish example ahead :/
type Vehicle struct {
    Make  string
    Model string
}

type Car struct {
    // You know... The doors that open up instead of out to the side ¯\_(ツ)_/¯ 
    VerticalDoors bool
    // Embedding, so for example, users will be able to access carObj.Vehicle.Make and carObj.Make now!
    // NB: This is *NOT* subclassing, so you won't be able to put a Car into a slice of type Vehicle, for instance!
    //     For use cases like that, you must utilize methods and interfaces (covered in the Methods and Interfaces sections, respectively)
    Vehicle
}

func main() {
    teslaModelX := Car{
        VerticalDoors: true,
        // NB: You can't set embedded fields in-line here, you must use the following explicit syntax
        Vehicle: Vehicle{
            Make: "Tesla",
            Model: "X",
        },
    }
    fmt.Println(teslaModelX) // Prints out {true {Tesla X}}
    // Access an embedded field from the parent
    fmt.Println(teslaModelX.Model) // Prints out X
}

Keep it Idiomatic!

  • Structs (and subsequently methods and interfaces) are a HUGE part of Go, so utilize them liberally

  • Generally when we want to expose an API for other developers, we try to accept interfaces rather than structs, because interfaces in Go are implicitly evaluated, whereas structs must be explicitly used (also further complicated by your dependency management tool, where sometimes you're just using a different copy of the same library and Go will refuse to compile your source, since it's not exactly the same struct per se)

  • Don't overuse struct embedding. It is not really a 'core' feature of the Go language, occasionally has some awkward/unexpected behaviors, and can often be avoided without introducing too much other overhead