Go - Structs

Intro

A struct is a collection of fields/properties. You can define new types as structs or interfaces. If you are coming from an object-oriented background, you can think of a struct to be a light class that supports composition but not inheritance.

Structs are blueprints — They are fixed and created at compile-time, but struct values fill them in runtime..

It’s like a class in OOP languages. Groups related data in a single type. You don’t need to define getters and setters on struct fields, they can be accessed automatically. However, note that only exported fields (capitalized) can be accessed from outside of a package.

Eg.

type VideoGame struct {
      Title string Genre string
      Published bool
  }

It is worth noting though that they are not the only way to create custom types below shows how you can use builtin types to create new types:

type MyString string

type IP string
type HostName string

type router map[HostName]IP

type HostList []Hostname

Declaring struct literals

Simple example:

type Point struct {
    X, Y int
}

var (
    p = Point{1, 2}  // has type Point
    q = &Point{1, 2} // has type *Point
    r = Point{X: 1}  // Y:0 is implicit
    s = Point{}      // X:0 and Y:0
)

Accesing fields using dot notation

package main

import (
    "fmt"
    "time"
)

type Point struct {
    X, Y int
}

func main() {
    p = Point{1, 2}
    fmt.Printf("Point is located at (%d, %d)", p.X, p.Y)
}

Initializing structs

Go supports the new expression to allocate a zeroed value of the requested type and to return a pointer to it.

x := new(int)

Here are some ways to initialize struct:

  1. We can initialize struct using struct literal, as covered earlier: p = Point{1, 2}
  2. Using new keyword: p = new(Point)
  3. Create constructor - This method is useful when zero value is not good enough.

Note that following expressions using new and an empty struct literal are equivalent and result in the same kind of allocation/initialization:

package main

import (
    "fmt"
)

type Point struct {
    X float64
    Y float64
}

func main() {
    x := new(Point)
    y := &Point{}
    fmt.Println(*x == *y) // outputs true
}

Note that slices, maps and channels are usually allocated using make so the data structure these types are built upon can be initialized.

Resources:

Adding behaviour or methods to a struct

We can also add behaviour to golang structs. Look at Golang methods for more.

Struct Equality

  • Two structs are equal if all their fields are equal.

  • Anonymous Fields: When the field names conflict the parent type takes priority.

More reading. The Go FAQ has some good information if you are interested in reading further: FAQ


See also