Go by Example: Structs
Structs are typed collections of fields. They are useful for grouping data together to form records. This example shows struct definition, initialization, pointers to structs, and anonymous structs.
Code
package main
import "fmt"
// 1. Defining a Struct
type Person struct {
Name string
Age int
}
// 2. Constructor Pattern
// Go doesn't have built-in constructors. We use factory functions.
func NewPerson(name string) *Person {
p := Person{Name: name}
p.Age = 42 // Default value logic
return &p // Returning a pointer is safe in Go (escape analysis)
}
func main() {
// 3. Creating a Struct
fmt.Println(Person{"Bob", 20})
// 4. Named Fields (Recommended)
fmt.Println(Person{Name: "Alice", Age: 30})
// 5. Omitted Fields
// Omitted fields get zero values.
fmt.Println(Person{Name: "Fred"}) // Age is 0
// 6. Pointers to Structs
// Go automatically dereferences pointers for struct fields.
ann := &Person{Name: "Ann", Age: 40}
fmt.Println(ann.Name) // Works same as (*ann).Name
// 7. Constructor usage
p := NewPerson("Jon")
fmt.Println("Factory:", p)
// 8. Anonymous Structs
// Useful for one-off data structures (e.g., in tests).
dog := struct {
Name string
IsGood bool
}{
Name: "Rex",
IsGood: true,
}
fmt.Println("Dog:", dog)
}
Explanation
Structs serve as the fundamental building block for defining complex, composite data types in Go, allowing developers to aggregate heterogeneous fields into a single, cohesive logical entity. Unlike classes in object-oriented paradigms, structs are purely data containers that do not inherently possess behavior; instead, methods are defined separately, promoting a clean separation of state and behavior that aligns with Go's composition-over-inheritance philosophy. This design facilitates the creation of clear, maintainable data models that are strictly typed and memory-efficient.
Go's handling of pointers to structs is particularly elegant, featuring automatic dereferencing that allows developers to access fields on a pointer variable with the same syntactic simplicity as a direct value. This syntactic sugar, combined with the language's escape analysis—which determines whether a variable should reside on the stack or the heap—enables developers to write safe, high-performance code that leverages pointer semantics for efficiency without the cognitive overhead typically associated with manual memory management in lower-level languages.
- Type Safety: Fields are strictly typed.
- Memory Layout: Fields are laid out contiguously in memory.
- Pass by Value: Structs are copied when passed to functions unless you use a pointer.
- Anonymous Structs: Great for temporary data grouping, like table-driven tests or JSON unmarshaling.

