【go】函数类型的作用

ops/2025/3/16 3:07:36/

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) boolfunc 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 stringport inttimeout time.DurationmaxConn 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 := initialValuefor _, 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 stringAge  int
}type SortBy func(p1, p2 *Person) booltype PersonSorter struct {people []Personless   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 := falsevar result interface{}return func() interface{} {if !computed {fmt.Println("执行昂贵计算...")// 模拟耗时操作time.Sleep(1 * time.Second)result = 42computed = true}return result}
}// 使用示例
func main() {// 创建惰性计算lazy := computeExpensiveValue()fmt.Println("惰性计算创建后,尚未执行计算")// 调用时才执行实际计算value := lazy()fmt.Println("第一次获取值:", value)// 再次调用不会重复计算value = lazy()fmt.Println("第二次获取值:", value)
}

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


http://www.ppmy.cn/ops/166105.html

相关文章

conda install 和 pip install 的区别

conda install 和 pip install 是两个常用的包安装命令&#xff0c;但它们在很多方面存在差异。 1. 所属管理系统不同 1.1 conda install conda install 是Anaconda和Miniconda发行版自带的包管理工具 conda 的安装命令。conda 是一个跨平台的开源包管理系统和环境管理系统&…

蓝桥杯 阶乘求值

问题描述 给定 nn&#xff0c;求 n!n! 除以 10000000071000000007 的余数。 其中 n!n! 表示 nn 的阶乘&#xff0c;值为从 11 连乘到 nn 的积&#xff0c;即 n!123…nn!123…n。 输入格式 输入一行包含一个整数 nn。 输出格式 输出一行&#xff0c;包含一个整数&#xff0c;表示…

LearnOpenGL-笔记-其四

上一篇笔记中结束了材质的内容&#xff0c;现在让我们进入新的部分&#xff1a; 光照贴图 光照贴图的概念其实非常简单&#xff0c;简单地说&#xff0c;我们希望不同的材质拥有不同的光照属性&#xff0c;所以不同的材质要应用不用的光照贴图&#xff0c;最常见的有我们的漫…

(七)Spring Boot学习——Redis使用

有部分内容是常用的&#xff0c;为了避免每次都查询数据库&#xff0c;将部分数据存入Redis。 一、 下载并安装 Redis Windows 版的 Redis 官方已不再维护&#xff0c;你可以使用 微软提供的 Redis for Windows 版本 或者 使用 WSL&#xff08;Windows Subsystem for Linux&a…

四元数 实部 虚部顺序,不同仿真器

一些库将四元数表示为 &#xff08;w,x,y,z&#xff09;&#xff0c;将实部定位为第一个元素。 而其他的一些库则将其 表示为 &#xff08;x,y,z, w&#xff09;。 QuaternionConventionSimulator/LibrarywxyzMuJoCo, SAPIEN, CoppeliaSim, IsaacSim, Gazebo, Blender, Taichi…

【Go每日一练】实现简单的控制台计算器

&#x1f47b;创作者&#xff1a;丶重明 &#x1f47b;创作时间&#xff1a;2025年3月7日 &#x1f47b;擅长领域&#xff1a;运维 目录 1.&#x1f636;‍&#x1f32b;️题目&#xff1a;简单的控制台计算器2.&#x1f636;‍&#x1f32b;️代码输出3.&#x1f636;‍&#…

Java高频面试之集合-10

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;详解红黑树&#xff1f;HashMap为什么不用二叉树/平衡树呢&#xff1f; 一、红黑树&#xff08;Red-Black Tree&#xff…

258.反转字符串中的单词

方法一&#xff1a; public class Solution {public String reverseWords(String s) {if(s.length()1&&!s.equals(" ")){return s;}List<String> resnew ArrayList<>();int start0;for(int i1;i<s.length();i){if(s.charAt(i)! && s…