219b83bfc0
Added comprehensive educational documentation to fill empty folders: ## Architecture Diagrams (8 files) - System architecture with layered design - Complete request/response flow diagrams - Middleware chain execution details - Handler organization structure - Data model relationships - Error handling flows - Template rendering pipeline - PDF generation process with Chromedp ## Go Patterns (9 files) - Pattern catalog and usage guide - Middleware pattern (HTTP chain composition) - Handler pattern (method-based organization) - Context pattern (request-scoped values) - Error wrapping (typed errors, chains) - Dependency injection (constructor-based) - Template pattern (rendering pipeline) - Singleton pattern (thread-safe instances) - Factory pattern (error/response constructors) ## Best Practices (2 files) - Best practices catalog and quick reference - Code organization (project structure, naming) All documentation includes: - Real examples from this project - ASCII diagrams for visualization - Best practices and anti-patterns - Testing examples - Performance considerations Documentation structure: - 20 markdown files - ~6,000+ lines of educational content - Cross-referenced between topics - Practical, project-based examples
Go Best Practices for This Project
This directory contains best practices and guidelines used in the CV website project, demonstrating real-world Go development standards.
Best Practices Catalog
- Code Organization - Package structure, file naming, project layout
- Error Handling - Error wrapping, custom errors, error patterns
- Testing - Unit tests, integration tests, benchmarks, test organization
- Performance - Optimization strategies, profiling, benchmarking
- Security - Input validation, XSS prevention, CSRF protection
- HTTP & Handlers - Handler patterns, middleware, request/response
- HTMX Integration - Server-side rendering, partial updates, Go + HTMX patterns
Quick Reference
Code Organization
project/
├── cmd/ Main applications
├── internal/ Private application code
│ ├── handlers/ HTTP handlers
│ ├── middleware/ HTTP middleware
│ ├── models/ Data models
│ ├── templates/ Template management
│ └── routes/ Route definitions
├── data/ Static data files
├── templates/ HTML templates
├── static/ Static assets
└── tests/ Test files
Error Handling
// Wrap errors with context
if err != nil {
return fmt.Errorf("operation failed: %w", err)
}
// Use typed errors
func InvalidLanguageError(lang string) *DomainError {
return NewDomainError(
ErrCodeInvalidLanguage,
fmt.Sprintf("Unsupported language: %s", lang),
http.StatusBadRequest,
)
}
Testing
// Table-driven tests
func TestFunction(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{"case1", "input1", "expected1"},
{"case2", "input2", "expected2"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Function(tt.input)
if got != tt.want {
t.Errorf("got %v, want %v", got, tt.want)
}
})
}
}
HTTP Handlers
// Use method receivers for related handlers
type CVHandler struct {
tmpl *templates.Manager
host string
}
func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request) {
// Handler logic
}
Middleware
// Standard middleware pattern
func MyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Pre-processing
next.ServeHTTP(w, r)
// Post-processing
})
}
Core Principles
1. Simplicity
- Clear is better than clever
- Explicit is better than implicit
- Simple solutions over complex ones
2. Readability
- Code is read more often than written
- Use descriptive names
- Comment why, not what
3. Consistency
- Follow established patterns
- Consistent formatting (gofmt)
- Consistent error handling
4. Performance
- Measure before optimizing
- Use profiling tools
- Optimize hot paths only
5. Security
- Validate all input
- Use context for timeouts
- Sanitize output
Common Pitfalls to Avoid
❌ DON'T
// DON'T ignore errors
data, _ := readFile(path)
// DON'T use panic for flow control
if invalid {
panic("invalid input")
}
// DON'T store context in structs
type Handler struct {
ctx context.Context // Wrong!
}
// DON'T use global mutable state
var globalConfig Config
globalConfig.Timeout = 30
// DON'T return naked values with named returns
func foo() (result string, err error) {
result = "value"
return // Confusing!
}
✅ DO
// DO handle errors explicitly
data, err := readFile(path)
if err != nil {
return fmt.Errorf("read file: %w", err)
}
// DO return errors for exceptional cases
if invalid {
return errors.New("invalid input")
}
// DO pass context as first parameter
func (h *Handler) Process(ctx context.Context, data Data) error {
// Use ctx
}
// DO use dependency injection
func NewHandler(config *Config) *Handler {
return &Handler{config: config}
}
// DO use explicit returns
func foo() (string, error) {
result := "value"
return result, nil
}
Tools & Commands
Formatting & Linting
# Format code
go fmt ./...
gofmt -s -w .
# Lint code
golangci-lint run
staticcheck ./...
# Vet code
go vet ./...
Testing
# Run tests
go test ./...
# Run with coverage
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Run benchmarks
go test -bench=. ./...
go test -bench=. -benchmem ./...
# Run specific test
go test -run TestFunctionName
Profiling
# CPU profiling
go test -cpuprofile=cpu.prof -bench=.
go tool pprof cpu.prof
# Memory profiling
go test -memprofile=mem.prof -bench=.
go tool pprof mem.prof
# Live profiling
go tool pprof http://localhost:8080/debug/pprof/profile
Build & Run
# Build
go build -o app ./cmd/server
# Run
go run ./cmd/server
# Build with optimizations
go build -ldflags="-s -w" -o app ./cmd/server
# Cross-compile
GOOS=linux GOARCH=amd64 go build -o app-linux ./cmd/server
Project-Specific Guidelines
File Naming
handler.go→cv.go,health.gohandler_pages.go→cv_pages.gohandler_htmx.go→cv_htmx.gohandler_test.go→cv_pages_test.go
Handler Organization
internal/handlers/
├── cv.go # Constructor
├── cv_pages.go # Page handlers
├── cv_htmx.go # HTMX handlers
├── cv_pdf.go # PDF handler
├── cv_helpers.go # Helper functions
├── types.go # Request/response types
├── errors.go # Error handling
└── *_test.go # Tests mirror source files
Middleware Chain Order
Recovery → Logger → SecurityHeaders → Preferences → Router
(outer) (inner)
Context Keys
// Use custom type for context keys
type contextKey string
const PreferencesKey contextKey = "preferences"
References
Official Resources
Community Resources
Tools
- golangci-lint - Linter aggregator
- staticcheck - Static analysis
- gopls - Language server
Learning Path
- Start with: Code Organization, HTTP Handlers
- Then learn: Error Handling, Testing
- Advanced: Performance, Security
- Mastery: HTMX Integration, Full Stack Patterns
Evolution of This Project
Phase 1: Basic Structure
- Simple handlers
- No middleware
- Manual cookie handling
Phase 2: Refactoring
- Handler split by responsibility
- Middleware introduction
- Context pattern adoption
Phase 3: Type Safety
- Request/response types
- Validation tags
- Typed errors
Phase 4: Testing & Performance
- Comprehensive test coverage
- Benchmark tests
- Performance profiling
Phase 5: Documentation
- Architecture diagrams
- Pattern documentation
- Best practices guide (this!)