Backend Go Programming Micro-Patterns (LLD Prep)
This document lists Go-specific design and implementation micro-patterns that a senior backend engineer should know.
Focus is on concurrency, structuring code, networking, error handling, and Go idioms.
🧩 Go Language & Struct Patterns
- Value vs. Pointer Receivers
- Value for immutability and small structs.
- Pointer for mutability and large structs.
- Interface-Oriented Design
- Define behavior contracts, not concrete types.
- Empty Interface (
interface{})- Avoid overuse, but useful for generics-like flexibility.
- Struct Embedding
- Composition over inheritance.
- Tagged Struct Fields
- JSON, DB, validation tags.
- Option Pattern with Functional Options
- Use functions to configure struct initialization.
- Zero Values as Defaults
- Ensure types work sensibly without explicit init.
🕳️ Error Handling Patterns
- Error Wrapping (
fmt.Errorf("%w"))- Preserve context for error chains.
- Sentinel Errors
- Predefined error values (
var ErrNotFound = errors.New("...")).
- Predefined error values (
- Error Inspection
errors.Isanderrors.Asfor unwrapping.
- Custom Error Types
- Include metadata (e.g., status codes).
- Panic vs. Error
- Panic only for unrecoverable state; recover at boundaries.
- Retry with Backoff
- Exponential with jitter for resilience.
🔄 Concurrency & Goroutine Patterns
- Worker Pool
- Limit concurrent goroutines, reuse workers.
- Pipeline Pattern
- Chain goroutines connected by channels.
- Fan-Out / Fan-In
- Distribute work across goroutines, aggregate results.
- Context Cancellation
- Use
context.Contextto propagate cancellation/deadlines.
- Use
- Ticker / Timer
- Scheduled tasks with
time.Ticker/time.After.
- Scheduled tasks with
- Semaphore via Channel
- Limit concurrency with buffered channels.
- ErrGroup
- Coordinated goroutine lifecycles with error propagation.
- Select Statement
- Multiplex channel operations.
- Non-Blocking Channel Operations
select { case ... default: }.
🌐 Networking & API Patterns
- HTTP Middleware Chain
- Compose request handling (
net/http, chi, echo).
- Compose request handling (
- Request Context Pattern
- Store request-scoped values in
context.Context.
- Store request-scoped values in
- Connection Pooling
- Use
http.Clientproperly (reuses TCP connections).
- Use
- gRPC Interceptors
- Middleware for RPC calls.
- Graceful Shutdown
http.Server.Shutdown(ctx)to drain requests.
- Rate Limiting
- Token bucket / leaky bucket via goroutines + channels.
- Circuit Breaker / Retry
- With libraries like
sony/gobreaker.
- With libraries like
- Idempotency Keys
- For safe retries in APIs.
📦 Data & Persistence Patterns
- Repository Pattern
- Abstract DB queries behind interfaces.
- Unit of Work
- Manage DB transaction lifecycle.
- Connection Pooling
- Proper use of
database/sqlconnection pools.
- Proper use of
- Context-Aware Queries
- Pass
ctxto DB calls for cancellation/timeouts.
- Pass
- Migration Pattern
- Use tools like
golang-migrateto manage schema evolution.
- Use tools like
- Caching
- In-memory (map + RWMutex), Redis, or Go LRU libs.
- CQRS (Command Query Responsibility Segregation)
- Separate reads and writes for scalability.
⚡ Performance Optimization Patterns
- Sync Pools
- Reuse objects with
sync.Pool.
- Reuse objects with
- Avoiding Goroutine Leaks
- Ensure all goroutines exit on context cancel.
- Zero-Copy I/O
io.Copystreams without buffering overhead.
- Batching
- Collect and process items in bulk.
- Lock Striping
- Shard state to reduce contention.
- Atomic Operations
- Use
sync/atomicfor counters, flags.
- Use
🔐 Security Patterns
- Input Validation
- Validate struct tags (e.g.,
validatorpkg).
- Validate struct tags (e.g.,
- Context-Aware Timeouts
- Prevent slowloris attacks by bounding request time.
- Secure Config Management
- Load secrets from env, vaults.
- JWT / Session Handling
- Secure token handling with rotation and expiry.
- Rate Limiting & Throttling
- Protect endpoints from abuse.
🛠️ Testing & Debugging Patterns
- Table-Driven Tests
- Use slices of structs for parameterized tests.
- Golden Files
- Store expected outputs in external files.
- Mock Interfaces
- Replace dependencies with fake implementations.
- Integration Testing with
httptest.Server- Spin up test servers easily.
- Benchmark Tests
- Use
testing.Bfor performance tests.
- Use
- Race Detector
go test -raceto catch concurrency issues.
- pprof & Tracing
- Profiling with built-in tooling.
🧮 Utility Micro-Patterns
- Context Keys
- Use custom types for keys to avoid collisions.
- Functional Options
- Clean configuration instead of many constructor args.
- Iterator via Channel
- Stream data with goroutines + channels.
- Pub/Sub with Channels
- In-memory event bus.
- Idempotent Initializers (
sync.Once)- Ensure single execution of initialization logic.
- Cancellation via Context
- Stop goroutines cooperatively.
✅ Senior-Level Interview Expectations
- Be able to compare trade-offs:
- Goroutines vs. worker pool vs. async I/O.
- Context cancel vs. manual signaling.
- Channels vs. locks.
- Sentinel errors vs. wrapped errors.
- Demonstrate idiomatic Go usage (simplicity, clarity).
- Show awareness of concurrency pitfalls (deadlocks, leaks).
- Highlight robustness (graceful shutdown, retries, timeouts).