【go】函数类型的作用

Go 语言函数类型的巧妙应用

函数类型在 Go 语言中非常强大,允许将函数作为值进行传递和操作。下面详细介绍函数类型的各种妙用:

1. 回调函数

// 定义一个函数类型
type Callback func(int) int

// 接受回调函数的函数
func processData(data []int, callback Callback) []int {
    
    
    result := make([]int, len(data))
    for i, v := range data {
    
    
        result[i] = callback(v)
    }
    return result
}

// 使用示例
func main() {
    
    
    numbers := []int{
    
    1, 2, 3, 4, 5}
    
    // 使用匿名函数作为回调
    doubled := processData(numbers, func(x int) int {
    
    
        return x * 2
    })
    
    // 使用已定义函数作为回调
    squared := processData(numbers, square)
    
    fmt.Println(doubled)  // [2 4 6 8 10]
    fmt.Println(squared)  // [1 4 9 16 25]
}

func square(x int) int {
    
    
    return x * x
}

2. 策略模式实现

type PaymentStrategy func(amount float64) bool

func processPayment(amount float64, strategy PaymentStrategy) bool {
    
    
    return strategy(amount)
}

// 各种支付策略
func creditCardPayment(amount float64) bool {
    
    
    // 信用卡支付逻辑
    return true
}

func alipayPayment(amount float64) bool {
    
    
    // 支付宝支付逻辑
    return true
}

// 使用示例
func pay(amount float64, paymentMethod string) bool {
    
    
    switch paymentMethod {
    
    
    case "credit":
        return processPayment(amount, creditCardPayment)
    case "alipay":
        return processPayment(amount, alipayPayment)
    default:
        return false
    }
}

3. 装饰器模式

type HttpHandler func(w http.ResponseWriter, r *http.Request)

// 日志装饰器
func LoggingDecorator(handler HttpHandler) HttpHandler {
    
    
    return func(w http.ResponseWriter, r *http.Request) {
    
    
        fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
        handler(w, r)
        fmt.Println("Request completed")
    }
}

// 认证装饰器
func AuthDecorator(handler HttpHandler) HttpHandler {
    
    
    return func(w http.ResponseWriter, r *http.Request) {
    
    
        // 检查认证信息
        if authenticate(r) {
    
    
            handler(w, r)
        } else {
    
    
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
        }
    }
}

// 使用装饰器
func main() {
    
    
    http.HandleFunc("/api/data", LoggingDecorator(AuthDecorator(handleData)))
    http.ListenAndServe(":8080", nil)
}

func handleData(w http.ResponseWriter, r *http.Request) {
    
    
    // 业务逻辑
}

4. 函数选项模式

type Server struct {
    
    
    host string
    port int
    timeout time.Duration
    maxConn int
}

type ServerOption func(*Server)

// 创建Server的选项函数
func WithHost(host string) ServerOption {
    
    
    return func(s *Server) {
    
    
        s.host = host
    }
}

func WithPort(port int) ServerOption {
    
    
    return func(s *Server) {
    
    
        s.port = port
    }
}

func WithTimeout(timeout time.Duration) ServerOption {
    
    
    return func(s *Server) {
    
    
        s.timeout = timeout
    }
}

func WithMaxConn(maxConn int) ServerOption {
    
    
    return func(s *Server) {
    
    
        s.maxConn = maxConn
    }
}

// 创建服务器
func NewServer(options ...ServerOption) *Server {
    
    
    // 设置默认值
    server := &Server{
    
    
        host:    "localhost",
        port:    8080,
        timeout: 30 * time.Second,
        maxConn: 100,
    }
    
    // 应用所有选项
    for _, option := range options {
    
    
        option(server)
    }
    
    return server
}

// 使用示例
func main() {
    
    
    server := NewServer(
        WithHost("example.com"),
        WithPort(9000),
        WithTimeout(60 * time.Second),
    )
    // 使用server...
}

5. 中间件链

type Middleware func(http.Handler) http.Handler

// 中间件链
func Chain(middlewares ...Middleware) Middleware {
    
    
    return func(next http.Handler) http.Handler {
    
    
        for i := len(middlewares) - 1; i >= 0; i-- {
    
    
            next = middlewares[i](next)
        }
        return next
    }
}

// 使用示例
func main() {
    
    
    handler := http.HandlerFunc(finalHandler)
    
    // 创建中间件链
    chain := Chain(
        loggingMiddleware,
        authMiddleware,
        rateLimitMiddleware,
    )
    
    // 应用中间件链
    http.Handle("/api", chain(handler))
    http.ListenAndServe(":8080", nil)
}

6. 延迟执行与钩子函数

type ShutdownHook func()

type App struct {
    
    
    shutdownHooks []ShutdownHook
}

func (a *App) AddShutdownHook(hook ShutdownHook) {
    
    
    a.shutdownHooks = append(a.shutdownHooks, hook)
}

func (a *App) Shutdown() {
    
    
    // 按照注册顺序的相反顺序执行钩子
    for i := len(a.shutdownHooks) - 1; i >= 0; i-- {
    
    
        a.shutdownHooks[i]()
    }
}

// 使用示例
func main() {
    
    
    app := &App{
    
    }
    
    // 注册数据库关闭钩子
    app.AddShutdownHook(func() {
    
    
        fmt.Println("关闭数据库连接")
    })
    
    // 注册文件清理钩子
    app.AddShutdownHook(func() {
    
    
        fmt.Println("清理临时文件")
    })
    
    // 应用运行...
    
    // 关闭应用
    app.Shutdown()
}

7. 操作集合的函数

type FilterFunc func(int) bool
type MapFunc func(int) int
type ReduceFunc func(int, int) int

// 过滤集合
func Filter(nums []int, filter FilterFunc) []int {
    
    
    result := []int{
    
    }
    for _, n := range nums {
    
    
        if filter(n) {
    
    
            result = append(result, n)
        }
    }
    return result
}

// 映射集合
func Map(nums []int, mapper MapFunc) []int {
    
    
    result := make([]int, len(nums))
    for i, n := range nums {
    
    
        result[i] = mapper(n)
    }
    return result
}

// 归约集合
func Reduce(nums []int, initialValue int, reducer ReduceFunc) int {
    
    
    result := initialValue
    for _, n := range nums {
    
    
        result = reducer(result, n)
    }
    return result
}

// 使用示例
func main() {
    
    
    numbers := []int{
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    // 过滤偶数
    evens := Filter(numbers, func(n int) bool {
    
    
        return n%2 == 0
    })
    
    // 将数字翻倍
    doubled := Map(evens, func(n int) int {
    
    
        return n * 2
    })
    
    // 求和
    sum := Reduce(doubled, 0, func(acc, n int) int {
    
    
        return acc + n
    })
    
    fmt.Println("结果:", sum) // 60
}

8. 依赖注入

type UserRepository interface {
    
    
    FindByID(id int) (User, error)
}

type UserService struct {
    
    
    repo UserRepository
}

func NewUserService(repo UserRepository) *UserService {
    
    
    return &UserService{
    
    repo: repo}
}

// 测试时可以轻松注入模拟实现
func TestUserService(t *testing.T) {
    
    
    mockRepo := &MockUserRepository{
    
    
        FindByIDFunc: func(id int) (User, error) {
    
    
            return User{
    
    ID: id, Name: "测试用户"}, nil
        },
    }
    
    service := NewUserService(mockRepo)
    // 测试 service...
}

9. 自定义排序

type Person struct {
    
    
    Name string
    Age  int
}

type SortBy func(p1, p2 *Person) bool

type PersonSorter struct {
    
    
    people []Person
    less   SortBy
}

func (s PersonSorter) Len() int           {
    
     return len(s.people) }
func (s PersonSorter) Swap(i, j int)      {
    
     s.people[i], s.people[j] = s.people[j], s.people[i] }
func (s PersonSorter) Less(i, j int) bool {
    
     return s.less(&s.people[i], &s.people[j]) }

// 使用示例
func main() {
    
    
    people := []Person{
    
    
        {
    
    "张三", 30},
        {
    
    "李四", 25},
        {
    
    "王五", 35},
    }
    
    // 按年龄排序
    sort.Sort(PersonSorter{
    
    
        people: people,
        less: func(p1, p2 *Person) bool {
    
    
            return p1.Age < p2.Age
        },
    })
    
    fmt.Println("按年龄排序:", people)
    
    // 按姓名排序
    sort.Sort(PersonSorter{
    
    
        people: people,
        less: func(p1, p2 *Person) bool {
    
    
            return p1.Name < p2.Name
        },
    })
    
    fmt.Println("按姓名排序:", people)
}

10. 惰性计算

type LazyEval func() interface{
    
    }

func computeExpensiveValue() LazyEval {
    
    
    computed := false
    var result interface{
    
    }
    
    return func() interface{
    
    } {
    
    
        if !computed {
    
    
            fmt.Println("执行昂贵计算...")
            // 模拟耗时操作
            time.Sleep(1 * time.Second)
            result = 42
            computed = true
        }
        return result
    }
}

// 使用示例
func main() {
    
    
    // 创建惰性计算
    lazy := computeExpensiveValue()
    
    fmt.Println("惰性计算创建后,尚未执行计算")
    
    // 调用时才执行实际计算
    value := lazy()
    fmt.Println("第一次获取值:", value)
    
    // 再次调用不会重复计算
    value = lazy()
    fmt.Println("第二次获取值:", value)
}

函数类型使 Go 拥有了函数式编程的部分能力,同时保持了语言的简洁性和性能,这使得它在构建灵活、可测试和可维护的代码时非常有价值。