golang函数包装器设计模式
golang函数包装器设计模式
1. 基础函数包装器
package main
import (
"fmt"
"time"
)
// 原始函数
func ProcessData(input string) string {
time.Sleep(100 * time.Millisecond)
return "Processed: " + input
}
// 包装器函数类型
type Processor func(string) string
// 计时包装器
func WithTimer(fn Processor) Processor {
return func(input string) string {
start := time.Now()
result := fn(input)
elapsed := time.Since(start)
fmt.Printf("Function took %v\n", elapsed)
return result
}
}
// 日志包装器
func WithLogger(fn Processor) Processor {
return func(input string) string {
fmt.Printf("Starting processing: %s\n", input)
result := fn(input)
fmt.Printf("Finished processing: %s\n", input)
return result
}
}
func main() {
// 使用包装器
processor := WithLogger(WithTimer(ProcessData))
result := processor("test data")
fmt.Println("Result:", result)
}
2. 中间件模式(类似HTTP中间件)
package main
import (
"fmt"
"strings"
)
// 中间件函数类型
type Middleware func(string) (string, error)
// 认证中间件
func AuthMiddleware(next Middleware) Middleware {
return func(input string) (string, error) {
if !strings.Contains(input, "token=") {
return "", fmt.Errorf("unauthorized")
}
return next(input)
}
}
// 验证中间件
func ValidationMiddleware(next Middleware) Middleware {
return func(input string) (string, error) {
if len(input) == 0 {
return "", fmt.Errorf("input cannot be empty")
}
return next(input)
}
}
// 业务逻辑函数
func BusinessLogic(input string) (string, error) {
return "Business result: " + input, nil
}
func main() {
// 组合中间件
handler := AuthMiddleware(ValidationMiddleware(BusinessLogic))
// 测试
result, err := handler("token=abc data=test")
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Success:", result)
}
}
3. 带配置的装饰器
package main
import (
"fmt"
"sync"
)
// 原始接口
type Calculator interface {
Calculate(x, y int) int
}
// 基础实现
type BasicCalculator struct{}
func (b BasicCalculator) Calculate(x, y int) int {
return x + y
}
// 缓存装饰器
type CachedCalculator struct {
calculator Calculator
cache sync.Map
}
func NewCachedCalculator(calc Calculator) *CachedCalculator {
return &CachedCalculator{
calculator: calc,
}
}
func (c *CachedCalculator) Calculate(x, y int) int {
key := fmt.Sprintf("%d+%d", x, y)
// 检查缓存
if val, ok := c.cache.Load(key); ok {
fmt.Printf("Cache hit for %s\n", key)
return val.(int)
}
// 计算并缓存
result := c.calculator.Calculate(x, y)
c.cache.Store(key, result)
fmt.Printf("Cache miss for %s\n", key)
return result
}
// 日志装饰器
type LoggingCalculator struct {
calculator Calculator
}
func NewLoggingCalculator(calc Calculator) *LoggingCalculator {
return &LoggingCalculator{calculator: calc}
}
func (l *LoggingCalculator) Calculate(x, y int) int {
fmt.Printf("Calculating %d + %d\n", x, y)
result := l.calculator.Calculate(x, y)
fmt.Printf("Result: %d\n", result)
return result
}
func main() {
basic := BasicCalculator{}
// 多层装饰
calculator := NewLoggingCalculator(
NewCachedCalculator(basic),
)
fmt.Println("Result:", calculator.Calculate(10, 20))
fmt.Println("Result:", calculator.Calculate(10, 20)) // 缓存命中
}
4. 函数链式包装
package main
import (
"fmt"
"strconv"
)
// 函数类型
type StringProcessor func(string) string
// 链式包装器
func Chain(processors ...StringProcessor) StringProcessor {
return func(input string) string {
result := input
for _, processor := range processors {
result = processor(result)
}
return result
}
}
// 各种处理函数
func TrimProcessor(input string) string {
return "trimmed_" + input
}
func UpperProcessor(input string) string {
return "UPPER_" + input
}
func ReverseProcessor(input string) string {
runes := []rune(input)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func CountProcessor(input string) string {
return input + "_len:" + strconv.Itoa(len(input))
}
func main() {
// 创建处理链
pipeline := Chain(
TrimProcessor,
UpperProcessor,
ReverseProcessor,
CountProcessor,
)
result := pipeline("hello world")
fmt.Println("Result:", result)
}
5. 错误处理包装器
package main
import (
"errors"
"fmt"
)
// 带错误的函数类型
type RiskyProcessor func(int) (int, error)
// 重试包装器
func WithRetry(maxAttempts int, fn RiskyProcessor) RiskyProcessor {
return func(input int) (int, error) {
var lastErr error
for attempt := 1; attempt <= maxAttempts; attempt++ {
result, err := fn(input)
if err == nil {
fmt.Printf("Success on attempt %d\n", attempt)
return result, nil
}
lastErr = err
fmt.Printf("Attempt %d failed: %v\n", attempt, err)
if attempt < maxAttempts {
fmt.Println("Retrying...")
}
}
return 0, fmt.Errorf("all %d attempts failed: %w", maxAttempts, lastErr)
}
}
// 模拟可能失败的函数
func UnstableDivide(x int) (int, error) {
if x%3 == 0 { // 模拟随机失败
return 0, errors.New("division failed")
}
return 100 / x, nil
}
func main() {
// 使用重试包装器
processor := WithRetry(3, UnstableDivide)
for i := 1; i <= 5; i++ {
result, err := processor(i)
if err != nil {
fmt.Printf("Input %d: Error: %v\n", i, err)
} else {
fmt.Printf("Input %d: Result: %d\n", i, result)
}
}
}
关键点总结:
高阶函数:Go中函数是一等公民,可以作为参数和返回值
函数类型:使用type定义函数签名,增强可读性
闭包:包装器通常返回闭包函数
链式组合:多个包装器可以组合使用
接口包装:可以通过结构体实现接口来装饰对象

