Structs

Go · Essentials · 10 min

Structs are how you model data in Go; there are no classes.

A struct is a typed collection of named fields:

type User struct {
	ID    int
	Name  string
	Admin bool
}

Create values with a composite literal. Prefer naming the fields, User{ID: 1, Name: "Ann"}; omitted fields get their zero values, and the code keeps compiling when fields are added. The positional form User{1, "Ann", false} must list every field in order and breaks when the struct changes.

Access fields with a dot: u.Name. Field visibility follows the package rule — upper-case fields are exported, which also controls whether packages like encoding/json can see them.

Structs are values. Assigning v := u or passing u to a function copies all fields; changing the copy doesn't touch the original. To share and mutate one value, use a pointer (next lesson). Two structs are comparable with == when all their fields are comparable, which also makes them usable as map keys.

Anonymous structs, point := struct{ X, Y int }{1, 2}, are handy for one-off data such as test tables. The empty struct struct{} takes zero bytes and is used for set values and signal-only channels.

A common pattern is a constructor function named NewThing that validates input and returns a ready-to-use value — Go has no constructors built in, so this is a convention, not a language feature.

Example

package main

import "fmt"

type Point struct {
	X, Y int
}

type Rect struct {
	Min, Max Point
	Label    string
}

func main() {
	r := Rect{Min: Point{0, 0}, Max: Point{4, 3}, Label: "box"}
	w := r.Max.X - r.Min.X
	fmt.Println(w, r.Label) // 4 box

	r2 := r // copies every field
	r2.Label = "copy"
	fmt.Println(r.Label, r2.Label) // box copy

	fmt.Println(Point{1, 2} == Point{1, 2}) // true
	fmt.Printf("%+v\n", r.Max)              // {X:4 Y:3}
}

Remember

  • Use keyed literals: T{Field: v}; missing fields are zero
  • Assignment copies a struct; use pointers to share
  • Structs with comparable fields support == and can be map keys

Watch out for

  • Using positional struct literals for types from other packages — they break when fields are added.

Check yourself

  1. `a := Point{1, 2}; b := a; b.X = 9` — what is `a.X`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: go.dev/ref/spec#Struct_types

Structs · Go · Topolearn