08 - Structs: Your Own Types
📋 Jump to TakeawaysA 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) // 0Accessing 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) // 20Structs 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