Go Struct
A struct in Go is a composite type that groups together zero or more named fields of possibly different types, giving you a way to model real-world records like a user, a product, or a coordinate.
Defining a Struct
You define a struct using the type and struct keywords, followed by a list of field names and their types. Struct definitions are usually placed at package level so they can be reused across your program. Field names conventionally start with an uppercase letter if you want them visible (exported) outside the package, or lowercase if they should stay private to the package.
Defining and using a simple struct
package main
import "fmt"
type Person struct {
Name string
Age int
City string
}
func main() {
var p Person
p.Name = "Elena"
p.Age = 29
p.City = "Lisbon"
fmt.Println(p.Name, p.Age, p.City)
}Struct Literals
Rather than creating a variable and assigning fields one by one, you can construct a fully populated struct in a single expression called a struct literal. There are two common styles: positional literals, where values are supplied in field order, and keyed literals, where each value is paired explicitly with its field name.
Keyed vs positional struct literals
package main
import "fmt"
type Point struct {
X int
Y int
}
func main() {
// Keyed literal - order does not matter, and it is self-documenting
a := Point{X: 3, Y: 4}
// Positional literal - order must match the struct definition exactly
b := Point{5, 12}
fmt.Println(a, b)
}Nested Structs and Pointers
Structs can contain other structs as fields, letting you build up richer models such as an Order that embeds a Customer. Go also lets you take the address of a struct with & to get a pointer, which is useful when you want a function to modify the original struct instead of a copy.
Nested struct with a pointer receiver
package main
import "fmt"
type Address struct {
City string
Country string
}
type Customer struct {
Name string
Address Address
}
func relocate(c *Customer, newCity string) {
c.Address.City = newCity
}
func main() {
cust := Customer{
Name: "Marco",
Address: Address{City: "Turin", Country: "Italy"},
}
relocate(&cust, "Milan")
fmt.Println(cust.Address.City)
}Structs vs Other Composite Types
It helps to know when a struct is the right tool compared to a map or a slice of separate variables.
- Use a struct when the set of fields is known ahead of time and each field has a distinct meaning.
- Give exported fields a capital letter if other packages need to read or write them.
- Prefer keyed struct literals so field order changes never introduce silent bugs.
- Pass a pointer to a struct when a function needs to mutate the caller's copy.
- Group related structs (like Address inside Customer) instead of flattening everything into one giant type.
Exercise: Go Struct
How do you access a field named Age on a struct instance p?