08 - Structs: Your Own Types

📋 Jump to Takeaways

A rectangle has a width and a height. A person has a name and an age. You could use separate variables for each, but that falls apart fast. What if you have ten rectangles? Twenty people? You need a way to group related data together. In Go, that's a struct.

Defining a Struct

type Rectangle struct {
	Width  float64
	Height float64
}

type creates a new type. Rectangle is the name. struct means it's a group of fields. Each field has a name and a type.

Creating a Struct

r := Rectangle{
	Width:  10.0,
	Height: 5.0,
}
fmt.Println(r) // {10 5}

You can let Go fill in zero values for fields you don't set:

r := Rectangle{Width: 10.0}
fmt.Println(r.Height) // 0

Accessing Fields

Use a dot:

r := Rectangle{Width: 10.0, Height: 5.0}

fmt.Println(r.Width)  // 10
fmt.Println(r.Height) // 5

r.Width = 20.0
fmt.Println(r.Width)  // 20

Structs in Functions

Functions receive copies. To modify a struct, return the updated version:

func scale(r Rectangle, factor float64) Rectangle {
	r.Width = r.Width * factor
	r.Height = r.Height * factor
	return r
}

func main() {
	r := Rectangle{Width: 10, Height: 5}
	r = scale(r, 2)
	fmt.Println(r) // {20 10}
}

Methods

A method is a function attached to a type. Instead of area(r), you write r.Area():

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func main() {
	r := Rectangle{Width: 10, Height: 5}
	fmt.Println(r.Area()) // 50
}

The (r Rectangle) before the function name is called a receiver. It means "this method belongs to the Rectangle type."

Methods that need to modify the struct return the modified copy. Later, when we cover pointers, you'll learn a cleaner way to do this:

func (r Rectangle) Scale(factor float64) Rectangle {
	r.Width = r.Width * factor
	r.Height = r.Height * factor
	return r
}

Multiple Struct Types

type Person struct {
	Name string
	Age  int
}

type Address struct {
	Street string
	City   string
}

Each type is independent. You can use them in the same program without any conflict.

Slices and Maps of Structs

people := []Person{
	{Name: "Alice", Age: 30},
	{Name: "Bob", Age: 25},
}

contacts := map[string]Person{
	"alice": {Name: "Alice", Age: 30},
}

Key Takeaways

  • type Name struct { } defines a new type with named fields
  • Access fields with a dot: p.Name, r.Width
  • Structs get zero values for unset fields
  • Functions receive copies of structs. Return the modified struct to update it
  • Methods attach functions to types: func (r Rectangle) Area() float64
  • Call methods with dot syntax: r.Area()
  • Structs work in slices ([]Person) and maps (map[string]Person)
  • If three variables always travel together, they belong in a struct

🚀 Ready to run?

Complete runnable examples for this lesson.

📝 Ready to test your knowledge?

Answer the quiz below to mark this lesson complete.

© 2026 ByteLearn.dev. Free courses for developers. · Privacy