Effective Embedding Patterns
Design Principles of Struct Embedding
Composition Over Inheritance
type Logger struct {
level string
}
func (l *Logger) Log(message string) {
fmt.Printf("[%s] %s\n", l.level, message)
}
type Service struct {
*Logger // Composition pattern
name string
}
Interface Embedding Strategies
graph TD
A[Base Interface] --> B[Extended Interface]
B --> C[Concrete Implementation]
Interface Composition Example
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
Embedding Patterns
Pattern |
Description |
Use Case |
Anonymous Embedding |
Direct struct inclusion |
Behavior inheritance |
Named Embedding |
Explicit field embedding |
Controlled composition |
Interface Embedding |
Combining interface capabilities |
Flexible type definitions |
Decorator Pattern with Embedding
type BaseService struct {
config map[string]string
}
type EnhancedService struct {
*BaseService
cache map[string]interface{}
}
Middleware Composition
type Middleware func(http.Handler) http.Handler
type Server struct {
middleware []Middleware
}
func (s *Server) Use(m Middleware) {
s.middleware = append(s.middleware, m)
}
Memory Efficiency
type SmallStruct struct {
data [8]byte
}
type LargeStruct struct {
SmallStruct // Zero-cost embedding
additional int
}
Advanced Embedding Techniques
Conditional Method Override
type BaseRepository struct {}
func (r *BaseRepository) Create(data interface{}) error {
// Default implementation
return nil
}
type SpecializedRepository struct {
*BaseRepository
}
func (r *SpecializedRepository) Create(data interface{}) error {
// Custom implementation
return fmt.Errorf("not implemented")
}
Error Handling Patterns
type Result struct {
Value interface{}
Error error
}
type Operation struct {
*Result
}
LabEx Best Practices
At LabEx, we recommend:
- Keep embeddings simple
- Prefer composition
- Use interface embedding for flexibility
- Minimize deep embedding hierarchies
Code Organization Strategies
graph TD
A[Core Struct] --> B[Embedded Utility]
A --> C[Embedded Behavior]
B --> D[Reusable Components]
- Zero-cost abstractions
- Compile-time type checking
- Efficient method dispatch
- Minimal runtime overhead
Conclusion
Effective struct embedding requires:
- Clear design intentions
- Understanding Go's composition model
- Careful method and field management