Structs

Structs group related pieces of data into a single type.

Without structs:

name := "Alice"
age := 30
country := "Vietnam"

As programs grow, managing many related variables becomes difficult.
A struct keeps related data together.


Defining a Struct

type Person struct {
    Name    string
    Age     int
    Country string
}

Read naturally as:

Define a new type named Person whose underlying type is a struct.


Creating a Struct

The most common way:

p := Person{
    Name:    "Alice",
    Age:     30,
    Country: "Vietnam",
}

Accessing Fields

Fields are accessed using dot notation.

fmt.Println(p.Name)
fmt.Println(p.Age)
fmt.Println(p.Country)

Modifying Fields

Fields can be updated directly.

p.Age = 31
 
fmt.Println(p.Age)

Output:

31

Zero Values

Declaring a struct without initialization:

var p Person

Results in:

Name     ""
Age      0
Country  ""

Go automatically initializes every field to its zero value.
This avoids uninitialized (garbage) values.
Common zero values:

TypeZero Value
int0
float0.0
boolfalse
string""
pointernil
slicenil
mapnil

Nested Structs

Structs can contain other structs.

type Address struct {
    City string
}
 
type Person struct {
    Name string
    Addr Address
}

Usage:

p := Person{
    Name: "Alice",
    Addr: Address{
        City: "Hanoi",
    },
}
 
fmt.Println(p.Addr.City)

Anonymous Structs

Temporary structs can be created without defining a named type.

point := struct {
    X int
    Y int
}{
    X: 10,
    Y: 20,
}

Useful for small, temporary data structures.


Structs vs Classes

Go does not have classes.

Instead, it separates:

  • Data (structs)
  • Behavior (functions and methods)
    Example:
type Person struct {
    Name string
}

Methods are attached later and are not defined inside the struct.


Why Go Uses

type Person struct {
}

Instead of

struct Person {
};

In Go, struct is only one possible underlying type.

Examples:

type Age int
 
type Name string
 
type Scores []int
 
type Lookup map[string]int
 
type Operation func(int, int) int
 
type Person struct {
    Name string
}

Notice the common pattern:

type NewType ExistingType

This gives Go a single, consistent way to define new types.


Exported vs Unexported Fields

Capitalization determines visibility.

Exported:

Name string

Visible from other packages.

Unexported:

name string

Visible only inside the current package.

Go replaces keywords like public and private with this simple naming convention.


Struct Formatting

Recommended style:

type Person struct {
    Name    string
    Age     int
    Country string
}

Run:

gofmt .

or

go fmt ./...

to automatically format Go source files.


Concepts Learned

Struct

type Person struct {
}

Groups related data into a new type.


Field Access

person.Name

Uses dot notation.


Field Assignment

person.Name = "Alice"

Updates a field.


Zero Values

Every field receives a default value when a struct is declared.

Nested Structs

Structs can contain other structs.


Anonymous Structs

Useful for temporary grouped data.


Type Declaration

type NewType ExistingType

A consistent mechanism for defining all user-defined types.


Session Summary

Topics covered:

  • Struct definition
  • Struct initialization
  • Field access
  • Field modification
  • Zero values
  • Nested structs
  • Anonymous structs
  • Exported vs unexported fields
  • Go’s unified type declaration syntax

Practical skills gained:

  • Modeling related data with structs
  • Organizing data into reusable types
  • Understanding Go’s approach to object-like data structures

Key Takeaways

  • Structs group related data together.
  • Go separates data (structs) from behavior (methods).
  • Every declared variable has a valid zero value.
  • Capitalization controls visibility between packages.
  • struct is not a special declaration—it is one possible underlying type used with the type keyword.

Next Topics