当前位置: 首页 > article >正文

【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 拥有了函数式编程的部分能力,同时保持了语言的简洁性和性能,这使得它在构建灵活、可测试和可维护的代码时非常有价值。


http://www.kler.cn/a/585619.html

相关文章:

  • 多线程(超详细) (ε≡٩(๑>₃<)۶ 一心向学)
  • 数据库技术
  • C++内建函数对象
  • QT基础十四、绘图
  • RabbitMQ (Java)学习笔记
  • 高安全可靠MCU芯片AS32X601应用解析
  • 【北上广深杭大厂AI算法面试题】计算机视觉篇...YOLOv4 相较于YOLOv3有哪些改进?速度更快还是更慢,为什么?(二)
  • 关于Django框架的面试题及其解析
  • 嵌入式2-按键
  • Python网络爬虫之BeautifulSoup库的使用流程和方法
  • 力扣hot100_二叉树(5)_python版本
  • 实验5 逻辑回归
  • 梯度下降法以及随机梯度下降法
  • 作业9 (2023-05-05 数组的定义和初始化)
  • 富文本编辑器(Rich Text Editor,RTE)
  • 矩阵交换行(信息学奥赛一本通-1119)
  • 基于NXP+FPGA永磁同步电机牵引控制单元(单板结构/机箱结构)
  • CMU15445(2023fall) Project #2 - Extendible Hash Index 匠心分析
  • 【搭建环境】windows环境redis\集群;rabbitmq
  • 在 Spring Boot 中实现基于 TraceId 的日志链路追踪