golang使用高阶函数优化业务功能

这篇具有很好参考价值的文章主要介绍了golang使用高阶函数优化业务功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

业务描述

        两个接口(新增Tag和更新Tag),在业务层均需要添加两个校验,校验Tag信息是否重复和Tag的数据中的编码是否重复。

基本实现

方式

        对应的增加两个校验的函数/方法,在接口实现中依次调用两个函数/方法进行校验。

优缺点

        实现简单;但重复代码多,后期再增加其他校验,扩展性较差。

高阶函数方式一

方式

        因为业务方法参数相同,业务层新增一个方法,包含一个函数类型参数(该函数即最终业务函数,新增/更新Tag),业务层新增方法:

func (t *TagUseCase) ValidateTag(ctx context.Context, req *Tag, f func(context.Context, *Tag) error) error {
   //校验一
   exists, err := t.repo.ValidateAppIdFieldExists(ctx, req.AppId, req.Field, req.IdString)
   if err != nil {
      return err
   }
   if exists {
      return errors.New(fmt.Sprintf("已存在:%v", req.Field))
   }
   //校验二
   flag, code := t.ValidateCodeUnique(req.Children)
   if flag {
      return errors.New(fmt.Sprintf("编码重复:%v", code))
   }
   //执行业务目标函数
   return f(ctx, req)
}

服务层调用:

func (s *TagService) CreateTag(ctx context.Context, req *pb.CreateTagRequest) (*pb.OperationTagReply, error) {
    //s.tuc.CreateTag为目标函数
	err := s.tuc.ValidateTag(ctx, tag, s.tuc.CreateTag)
	if err != nil {
		return nil, errors.New(0, err.Error(), "failed!")
	}
	return &pb.OperationTagReply{Msg: "success"}, nil
}

优缺点

        通过将目标函数参数化,将校验抽取到了一个方法中,后期如果增加其他校验,只需修改ValidateTag方法即可,有点类似于Java中的静态代理。重复代码很少,扩展性较好。但如果不同的业务需要的校验不完全相同,则存在问题。

高阶函数方式二

方式

        通过中间件实现(借鉴Kratos框架middleware),校验函数和目标函数的入参和返回值均相同(即使不同,可通过golang的闭包将函数包装成需要的函数签名),将其都作为一次处理,将所有的处理链接起来再执行。

定义中间件Handler类型:

定义中间件
type Handler func(ctx context.Context, req interface{}) error  #定义handler类型,即定义中间件和最终执行方法/函数的的声明
type Middleware func(Handler) Handler   # 定义Middle类型,即入参和返回值为相同类型的Handler,用于后面将其链接起来
# 将各中间件链接起来,next即最终要执行的函数,通过反向遍历的方式,将中间件按照添加的顺序依次链接,最先添加的在最外层,最先执行,结构类似:func(func(func(next)))
func Chain(m ...Middleware) Middleware {
   return func(next Handler) Handler {
      for i := len(m) - 1; i >= 0; i-- {
         next = m[i](next)
      }
      return next
   }
}

在业务层创建中间件:

func (t *TagUseCase) ValidatorTagExists() tagmiddleware.Middleware {
   return func(handler tagmiddleware.Handler) tagmiddleware.Handler {
      return func(ctx context.Context, req interface{}) (err error) {
         if v, ok := req.(*Tag); ok {
            exists, err := t.repo.ValidateAppIdFieldExists(ctx, v.AppId, v.Field, v.IdString)
            if err != nil {
               return err
            }
            if exists {
               return errors.New(fmt.Sprintf("该标签field已存在:%v", v.Field))
            }
         }
         return handler(ctx, req)
      }
   }
}

调用方式一:

#添加中间件:在业务层的结构体增加一个middleware字段,创建结构体时,将需要的中间件添加到该属性中
t.middleware = []tagmiddleware.Middleware{t.ValidatorTagExists(), t.ValidatorTagCodeRepeat()}

#提供给需要中间件的方法/函数调用: Chain首先获取到执行链,最终传入h进行调用
func (t *TagUseCase) Middleware(h tagmiddleware.Handler) tagmiddleware.Handler {
   return tagmiddleware.Chain(t.middleware...)(h)
}
最终调用:首先构建中间件,UpdateTag是最终要执行的方法。middleware(ctx,tag) 执行中间件和目标方法
middleware := s.tuc.Middleware(func(ctx context.Context, disposeReq interface{}) error {
   return s.tuc.UpdateTag(ctx, disposeReq.(*biz.Tag))
})
err = middleware(ctx, tag)

调用方式二:方式一提前指定了要执行那些中间件,不够灵活

#最终调用:在调用时指定要执行那些中间件。
middlewarex := tagmiddleware.Chain([]tagmiddleware.Middleware{s.tuc.ValidatorTagExists(), s.tuc.ValidatorTagCodeRepeat()}...)(func(ctx context.Context, disposeReq interface{}) error {
			return s.tuc.UpdateTag(ctx, disposeReq.(*biz.Tag))
		})
err = middlewarex(ctx, tag)

优缺点

        将校验和目标函数都作为handler处理,在调用时可以自定义设置要进行那些校验,灵活性高。但后期增加新的校验时,需要在多个调用的位置将新的校验handler添加到执行链中。文章来源地址https://www.toymoban.com/news/detail-731612.html

到了这里,关于golang使用高阶函数优化业务功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • react中使用高阶函数

    高阶函数, 如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数 1.若A函数,接收的参数是一个函数,那么A就可以称高阶函数 2.若A函数,调用的返回值依然是一个函数,那么A就可以称为高阶函数 常见的高级函数有:Promise,setTimeout(()={}),map(()={})等等

    2024年02月13日
    浏览(35)
  • 【业务功能篇86】微服务-springcloud-系统性能压力测试-jmeter-性能优化-JVM参数调优

      压力测试是给软件不断加压,强制其在极限的情况下运行,观察它可以运行到何种程度,从而发现性能缺陷,是通过搭建与实际环境相似的测试环境,通过测试程序在同一时间内或某一段时间内,向系统发送预期数量的交易请求、测试系统在不同压力情况下的效率状况,

    2024年02月10日
    浏览(39)
  • 【业务功能篇86】微服务-springcloud-系统性能压力测试-jmeter-性能优化-JVM参数调优-Nginx实现动静分离

      压力测试是给软件不断加压,强制其在极限的情况下运行,观察它可以运行到何种程度,从而发现性能缺陷,是通过搭建与实际环境相似的测试环境,通过测试程序在同一时间内或某一段时间内,向系统发送预期数量的交易请求、测试系统在不同压力情况下的效率状况,

    2024年02月07日
    浏览(50)
  • 使用Golang实现一套流程可配置,适用于广告、推荐系统的业务性框架——简单应用

    在诸如广告、推荐等系统中,我们往往会涉及过滤、召回和排序等过程。随着系统业务变得复杂,代码的耦合和交错会让项目跌入难以维护的深渊。于是模块化设计是复杂系统的必备基础。这篇文章介绍的业务框架脱胎于线上多人协作开发、高并发的竞价广告系统,在实践中

    2024年02月14日
    浏览(30)
  • golang - 函数的使用

    核心化编程 代码冗余问题 不利于代码维护 函数可以解决这个问题 函数 :为完成某一功能的程序指令(语句)的集合,称为函数 在 Go 中,函数分为:自定义函数(自己写的)、系统函数(系统提供的) 基本语法: 形参列表:表示函数的输入 函数中的语句:表示为了实现某

    2024年02月02日
    浏览(22)
  • Golang中函数的使用

    目录 函数 函数特点 函数的使用 函数定义 函数的参数 函数的返回值 函数的变量作用域 函数的递归调用 函数的可变参数 函数的闭包 函数的 defer 语句 注意 函数调用:函数调用时需要传递函数定义中要求的参数,并根据需要接收返回值。 匿名函数:匿名函数没有函数名,可

    2024年02月05日
    浏览(28)
  • Golang 函数定义及使用

    2024年02月13日
    浏览(27)
  • springboot业务功能实战(四)告别轮询,websocket的集成使用

    org.springframework.boot spring-boot-starter-websocket 加入配置类 @Configuration public class WebSocketConfig { /** 注入ServerEndpointExporter, 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 加入连接发送消

    2024年04月15日
    浏览(39)
  • Golang 程序性能优化利器 PGO 详解(一):简单介绍及使用

    在软件开发过程中,性能优化是不可或缺的一部分。无论是在Web服务、数据处理系统还是实时通信中,良好的性能都是至关重要的。Golang 从1.20版版本开始引入的 Profile Guided Optimization(PGO)机制能够帮助更好地优化 Go 程序的性能。 编译器在编译程序的时候会对程序做很多优

    2024年02月13日
    浏览(25)
  • 【人工智能】LLM 大模型的本质:一个超高阶函数(函数式编程思想,高阶函数),大模型的本质是有巨大数量的函数复合组成的超高阶函数

    LLM 大模型的本质:一个超高阶函数(函数式编程思想,高阶函数),大模型的本质是有巨大数量的函数复合组成的超高阶函数。 —— 禅与计算机程序设计艺术

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包