Go Gopher How to Go

A struct is a composite data type that groups together variables (fields) under a single name. Structs are fundamental in Go for creating complex data structures and modeling real-world entities.

💡 Key Points

  • Structs group related data into a single unit
  • Fields can be of different types
  • Structs are value types - assignment creates a copy
  • Use & to get a pointer to a struct
  • Struct fields are accessed with dot notation
  • Anonymous structs can be created inline
  • Structs can be embedded in other structs for composition
  • Exported fields start with uppercase letters

Defining and Using Structs

Define a struct type with the type keyword and create instances:

package main

import "fmt"

// Define a struct type
type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    // Create struct instance
    p1 := Person{Name: "Alice", Age: 30, City: "NYC"}
    fmt.Println("Person 1:", p1)
    
    // Create with field names (order doesn't matter)
    p2 := Person{
        Age:  25,
        Name: "Bob",
        City: "SF",
    }
    fmt.Println("Person 2:", p2)
    
    // Create without field names (must match order)
    p3 := Person{"Charlie", 35, "LA"}
    fmt.Println("Person 3:", p3)
    
    // Access fields
    fmt.Println("Name:", p1.Name)
    fmt.Println("Age:", p1.Age)
    
    // Modify fields
    p1.Age = 31
    fmt.Println("Updated age:", p1.Age)
}
Output:
Person 1: {Alice 30 NYC}
Person 2: {Bob 25 SF}
Person 3: {Charlie 35 LA}
Name: Alice
Age: 30
Updated age: 31

Struct Pointers

Use pointers to structs to avoid copying and enable modification:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func updateAge(p *Person, newAge int) {
    p.Age = newAge // Go automatically dereferences
}

func main() {
    // Create struct pointer with &
    p1 := &Person{Name: "Alice", Age: 30}
    fmt.Println("Before:", p1)
    
    // Access fields (automatic dereferencing)
    fmt.Println("Name:", p1.Name)
    
    // Pass pointer to function
    updateAge(p1, 31)
    fmt.Println("After:", p1)
    
    // new() allocates memory and returns pointer
    p2 := new(Person)
    p2.Name = "Bob"
    p2.Age = 25
    fmt.Println("Person 2:", p2)
}
Output:
Before: &{Alice 30}
Name: Alice
After: &{Alice 31}
Person 2: &{Bob 25}

Anonymous Structs and Embedding

Create inline structs and embed structs for composition:

package main

import "fmt"

type Address struct {
    Street string
    City   string
    State  string
}

type Person struct {
    Name    string
    Age     int
    Address // Embedded struct
}

func main() {
    // Anonymous struct (no type name)
    config := struct {
        Host string
        Port int
    }{
        Host: "localhost",
        Port: 8080,
    }
    fmt.Println("Config:", config)
    
    // Struct embedding
    p := Person{
        Name: "Alice",
        Age:  30,
        Address: Address{
            Street: "123 Main St",
            City:   "NYC",
            State:  "NY",
        },
    }
    
    // Access embedded fields directly
    fmt.Println("Name:", p.Name)
    fmt.Println("City:", p.City) // Can access Address.City directly
    fmt.Println("Full address:", p.Address)
}
Output:
Config: {localhost 8080}
Name: Alice
City: NYC
Full address: {123 Main St NYC NY}

Struct Declaration Patterns

PatternExampleDescription
Named structtype Person struct { Name string }Define a reusable struct type
Anonymous structstruct { X int; Y int }{1, 2}One-time use struct
Empty structstruct{}Zero-size type, useful for signals
Embedded structtype A struct { B }Composition via embedding
Pointer structp := &Person{}Create pointer to struct
With new()p := new(Person)Allocate and return pointer

Struct Tags

Use CaseExampleDescription
JSON encoding`json:"name"`Control JSON field names
Omit empty`json:"age,omitempty"`Skip zero values in JSON
Ignore field`json:"-"`Exclude from JSON
XML tags`xml:"person"`Control XML encoding
Validation`validate:"required"`Add validation rules
Database`db:"user_name"`Map to database columns

Struct Characteristics

FeatureDescriptionNotes
Value typeAssignment copies the structUse pointers to avoid copying
Zero valueAll fields set to their zero valuesStructs are never nil, pointers can be
ComparabilityComparable if all fields are comparableCan use == and !=
Field accessDot notation: s.fieldAutomatic pointer dereferencing
Exported fieldsUppercase = exported (public)Lowercase = unexported (private)
Memory layoutFields stored sequentiallyMay include padding for alignment

Common Patterns

PatternCodeUse Case
Constructor functionfunc NewPerson() *Person { }Create and initialize structs
Builder patternfunc (p *Person) WithAge(age int) *PersonFluent configuration
Options patternfunc WithTimeout(d time.Duration) OptionFlexible initialization
Embedding for mixinstype Manager struct { Person; Level int }Extend structs with new fields
Anonymous fieldstype Point struct { int; int }Simple coordinate structs