golang函数包装器设计模式

作者: adm 分类: go 发布时间: 2025-04-07

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定义函数签名,增强可读性
闭包:包装器通常返回闭包函数
链式组合:多个包装器可以组合使用
接口包装:可以通过结构体实现接口来装饰对象

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!