Structs & Embedding
A struct is a named group of fields. It's how Go builds
domain types, User, Order, Request,
anything with multiple attributes. Structs replace "classes" from
object-oriented languages, but with a simpler, composition-first mindset.
Learning objectives
- Define named and anonymous structs.
- Initialize structs with positional or named fields (and prefer named).
- Use embedded fields to compose types, not inherit.
- Attach metadata via struct tags (JSON, validate, etc).
- Compare structs with
==and know when you can't.
Defining a struct
type Person struct {
Name string
Age int
}
Conventions: capitalize field names to export them (visible outside the package, Chapter 18). Keep related fields together.
Initialization
// Zero value
var p Person // {Name:"" Age:0}
// Named fields (PREFERRED, survives refactors)
p := Person{Name: "Alice", Age: 30}
// Positional (fragile, avoid in production code)
p := Person{"Alice", 30}
// Partial, other fields get zero values
p := Person{Name: "Alice"}
Field access
p := Person{Name: "Alice", Age: 30}
fmt.Println(p.Name) // Alice
p.Age++ // 31
Access works through both values and pointers, Go auto-dereferences:
pp := &p
fmt.Println(pp.Name) // Alice, no explicit (*pp).Name needed
Nested and anonymous structs
type Address struct { City, Country string }
type User struct {
Name string
Address Address // nested
}
// Anonymous struct, inline, one-off
config := struct {
Host string
Port int
}{
Host: "localhost",
Port: 8080,
}
Anonymous structs are handy in tests and one-shot data carriers. Don't use them for anything reused, give it a name.
Embedding: composition, not inheritance
Instead of class inheritance, Go has embedded fields , declare a field with only a type name, and that type's fields and methods are promoted:
type Entity struct {
ID int
CreatedAt time.Time
}
type User struct {
Entity // embedded, no field name!
Name string
Email string
}
u := User{
Entity: Entity{ID: 1, CreatedAt: time.Now()},
Name: "Alice",
}
fmt.Println(u.ID) // 1, promoted from Entity
fmt.Println(u.Entity.ID) // 1: also accessible explicitly
This is Go's idiom for sharing common fields and behavior.
User is not an Entity (no inheritance),
but it has one and its fields look like they belong to
User. Methods work the same way: if Entity
has a Save() method, u.Save() works too
(Chapter 20).
Comparing structs
Structs are ==-comparable if all their
fields are:
p1 := Person{"Alice", 30}
p2 := Person{"Alice", 30}
fmt.Println(p1 == p2) // true
Struct containing a slice, map, or function? Not comparable. Use
reflect.DeepEqual for those, or write a method:
type Order struct {
Items []string // slice makes this non-comparable with ==
}
The empty struct, struct{}
A struct with no fields takes zero bytes. Useful as a "marker" value:
// A "set" in Go
set := map[string]struct{}{
"apple": {},
"banana": {},
}
if _, ok := set["apple"]; ok { /* … */ }
// Signal-only channel, Chapter 25
done := make(chan struct{})
close(done)
Check your understanding
Practice exercises
Model a Book
Define a Book struct with Title, Author, Year (int), and Tags ([]string). Write a function summarize(b Book) string that returns e.g. "The Go Programming Language by Donovan & Kernighan (2015)".
Show solution
type Book struct {
Title string
Author string
Year int
Tags []string
}
func summarize(b Book) string {
return fmt.Sprintf("%s by %s (%d)", b.Title, b.Author, b.Year)
}
Embedding in practice
Define a Timestamped struct with CreatedAt and UpdatedAt time fields. Then define Order and User structs that both embed Timestamped. Confirm that u.CreatedAt works.
Show solution
import "time"
type Timestamped struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
Timestamped
Name string
Email string
}
type Order struct {
Timestamped
ID int
Total float64
}
func main() {
u := User{
Timestamped: Timestamped{CreatedAt: time.Now()},
Name: "Alice",
}
fmt.Println(u.CreatedAt) // promoted field
}
Further reading
- Go spec, Struct types
- Effective Go, Embedding
encoding/json: the most common struct-tag user (Chapter 29)
Structs, the shape of your data.