Advanced Techniques
Functional Programming Patterns
Closures enable powerful functional programming techniques in Go, allowing for more flexible and composable code.
Function Factories
func multiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}
func main() {
double := multiplier(2)
triple := multiplier(3)
fmt.Println(double(5)) // Outputs: 10
fmt.Println(triple(5)) // Outputs: 15
}
Memoization Technique
func memoize(fn func(int) int) func(int) int {
cache := make(map[int]int)
return func(n int) int {
if val, exists := cache[n]; exists {
return val
}
result := fn(n)
cache[n] = result
return result
}
}
func expensiveCalculation(n int) int {
// Simulate a complex calculation
time.Sleep(time.Second)
return n * n
}
func main() {
cachedCalculation := memoize(expensiveCalculation)
fmt.Println(cachedCalculation(5)) // Slow first call
fmt.Println(cachedCalculation(5)) // Instant cached call
}
Advanced Closure Patterns
Pattern |
Description |
Use Case |
Decorator |
Wraps and enhances functions |
Adding logging, timing |
Middleware |
Intercepts and modifies function behavior |
Request processing |
State Machine |
Manages complex state transitions |
Event-driven programming |
Middleware Example
type Middleware func(http.HandlerFunc) http.HandlerFunc
func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("Request: %s %s", r.Method, r.URL)
next.ServeHTTP(w, r)
}
}
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Authentication logic
if !isAuthenticated(r) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
}
}
Closure Composition Visualization
graph TD
A[Original Function] --> B[Middleware 1]
B --> C[Middleware 2]
C --> D[Final Execution]
Context and Closure Interaction
func createContextHandler(ctx context.Context) func() {
return func() {
select {
case <-ctx.Done():
log.Println("Context cancelled")
default:
// Perform background task
}
}
}
- Minimize captured variable scope
- Avoid capturing large objects
- Use value capture when possible
- Be mindful of memory allocation
At LabEx, we recommend carefully designing closures to balance flexibility and performance.
Error Handling in Closures
func safeExecute(fn func() error) func() error {
return func() error {
defer func() {
if r := recover(); r != nil {
log.Printf("Recovered from panic: %v", r)
}
}()
return fn()
}
}
Advanced Use Cases
- Dependency injection
- Configuration management
- Lazy evaluation
- Concurrent programming patterns