Structs
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)
}Person 1: {Alice 30 NYC}
Person 2: {Bob 25 SF}
Person 3: {Charlie 35 LA}
Name: Alice
Age: 30
Updated age: 31Struct 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)
}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)
}Config: {localhost 8080}
Name: Alice
City: NYC
Full address: {123 Main St NYC NY}Struct Declaration Patterns
| Pattern | Example | Description |
|---|---|---|
| Named struct | type Person struct { Name string } | Define a reusable struct type |
| Anonymous struct | struct { X int; Y int }{1, 2} | One-time use struct |
| Empty struct | struct{} | Zero-size type, useful for signals |
| Embedded struct | type A struct { B } | Composition via embedding |
| Pointer struct | p := &Person{} | Create pointer to struct |
| With new() | p := new(Person) | Allocate and return pointer |
Struct Tags
| Use Case | Example | Description |
|---|---|---|
| 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
| Feature | Description | Notes |
|---|---|---|
| Value type | Assignment copies the struct | Use pointers to avoid copying |
| Zero value | All fields set to their zero values | Structs are never nil, pointers can be |
| Comparability | Comparable if all fields are comparable | Can use == and != |
| Field access | Dot notation: s.field | Automatic pointer dereferencing |
| Exported fields | Uppercase = exported (public) | Lowercase = unexported (private) |
| Memory layout | Fields stored sequentially | May include padding for alignment |
Common Patterns
| Pattern | Code | Use Case |
|---|---|---|
| Constructor function | func NewPerson() *Person { } | Create and initialize structs |
| Builder pattern | func (p *Person) WithAge(age int) *Person | Fluent configuration |
| Options pattern | func WithTimeout(d time.Duration) Option | Flexible initialization |
| Embedding for mixins | type Manager struct { Person; Level int } | Extend structs with new fields |
| Anonymous fields | type Point struct { int; int } | Simple coordinate structs |