Anonymous Structs and Composition
Embedding and struct-based code reuse
Anonymous Structs and Composition is a free Go Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Anonymous Structs
An anonymous struct has no named type. It's defined inline and is useful for short-lived data, table-driven tests, and one-off groupings:
package main
import "fmt"
func main() {
point := struct{ X, Y int }{X: 3, Y: 7}
fmt.Println(point.X, point.Y)
}Anonymous Structs in Table Tests
A common Go idiom uses a slice of anonymous structs for table-driven tests:
package main
import "fmt"
func double(n int) int { return n * 2 }
func main() {
tests := []struct{ input, want int }{
{1, 2}, {5, 10}, {0, 0},
}
for _, tt := range tests {
got := double(tt.input)
if got != tt.want {
fmt.Printf("FAIL: double(%d) = %d, want %d\n", tt.input, got, tt.want)
}
}
fmt.Println("all tests passed")
}Struct Embedding
Embedding a type inside a struct promotes its fields and methods to the outer struct:
package main
import "fmt"
type Animal struct{ Name string }
func (a Animal) Speak() string { return a.Name + " speaks" }
type Dog struct {
Animal // embedded
Breed string
}
func main() {
d := Dog{Animal: Animal{"Rex"}, Breed: "Labrador"}
fmt.Println(d.Name) // promoted field
fmt.Println(d.Speak()) // promoted method
}Multiple Embedding
A struct can embed multiple types. Conflicts (same field/method name) must be resolved explicitly:
package main
import "fmt"
type Logger struct{}
func (Logger) Log(s string) { fmt.Println("[LOG]", s) }
type Metrics struct{}
func (Metrics) Count() int { return 42 }
type Service struct {
Logger
Metrics
Name string
}
func main() {
svc := Service{Name: "auth"}
svc.Log("started") // from Logger
fmt.Println(svc.Count()) // from Metrics
}Embedding vs Inheritance
Go has no class inheritance. Embedding is composition:
- Embedding promotes fields and methods, but the outer type is not a subtype
- You cannot pass a
Dogwhere anAnimalis expected - Use interfaces for polymorphism, embedding for code reuse
Overriding Promoted Methods
The outer struct can shadow an embedded method by defining its own:
package main
import "fmt"
type Base struct{}
func (Base) Hello() string { return "Base hello" }
type Child struct{ Base }
func (Child) Hello() string { return "Child hello" } // shadows Base.Hello
func main() {
c := Child{}
fmt.Println(c.Hello()) // Child hello
fmt.Println(c.Base.Hello()) // Base hello (explicit)
}Anonymous Struct for Config
Use an anonymous struct to group related config without defining a named type:
package main
import "fmt"
func main() {
cfg := struct {
Host string
Port int
TLS bool
}{
Host: "api.example.com",
Port: 443,
TLS: true,
}
fmt.Println(cfg)
}Embedding an Interface
Embedding an interface in a struct is useful for mocking and default implementations:
package main
import "fmt"
type Reader interface{ Read() string }
type Mock struct{ Reader } // embed interface
func main() {
m := Mock{}
fmt.Printf("%T\n", m.Reader) // <nil> — not set
// Assign a real impl at test time:
_ = m
}Struct Composition Pitfalls
Watch out for:
- Ambiguous selectors when two embedded types have the same field/method name
- Nil embedded pointer causing a panic when you call methods on it
- Forgetting that embedding is not inheritance — you can't substitute the outer type for the embedded type
Comparing Anonymous Structs
Two anonymous structs with the same field names and types are assignable to each other if their tags also match:
package main
import "fmt"
func main() {
a := struct{ X, Y int }{1, 2}
b := struct{ X, Y int }{1, 2}
fmt.Println(a == b) // true
}Quick Check
What does embedding a type in a struct achieve?
Recap: Composition
Key takeaways:
- Anonymous structs are great for table tests and short-lived data
- Embedding promotes fields and methods — it's composition, not inheritance
- Outer types can shadow embedded methods
- Resolve ambiguous selectors explicitly
- Use interfaces for polymorphism
Practice Prompt
Create a TimestampedRecord struct that embeds a Timestamp struct{ CreatedAt, UpdatedAt string } and a Data struct{ Key, Value string }. Instantiate it and print all promoted fields.
Frequently asked questions
Is the “Anonymous Structs and Composition” lesson free?
Yes — the full text of “Anonymous Structs and Composition” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.
What will I learn in “Anonymous Structs and Composition”?
Embedding and struct-based code reuse You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Go Academy?
No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Anonymous Structs and Composition” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Go Academy lesson?
Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Defining and Using Structs
- Methods on Structs
- Constructor Patterns
- Anonymous Structs and Composition