golang 链式调用


文章目录

  • golang 链式调用
  • 前言
  • 一、什么是「责任链模式」?
  • 二、「责任链模式」的具体优势
  • 三、代码案例
    • search.go
    • orders.go
  • 总结

前言

我们在写golang 代码的时候经常会出现我想有一个可变参数来确认初始化变量的问题或者针对于按照多种条件查询返回查询结果。

我个人比较推崇使用责任链模式(链式调用)的方式来处理,这样的代码维护简单容易理解。


一、什么是「责任链模式」?

首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,然后在这一系列对象中传递请求对象,直到被处理为止。

我们从概念中可以看出责任链模式有如下明显的优势:

按职责划分:解耦
对象链:逻辑清晰

但是有一点直到被处理为止,代表最终只会被一个实际的业务对象执行了实际的业务逻辑,明显适用的场景并不多。但是除此之外,上面的那两点优势还是让人很心动,所以,为了适用于目前所接触的绝大多数业务场景,把概念进行了简单的调整,如下:

首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,直到“链路结束”为止。(结束:异常结束,或链路执行完毕结束)

简单的直到“链路结束”为止转换可以让我们把责任链模式适用于任何复杂的业务场景。

二、「责任链模式」的具体优势

直观:一眼可观的业务调用过程
无限扩展:可无限扩展的业务逻辑
高度封装:复杂业务代码依然高度封装
极易被修改:复杂业务代码下修改代码只需要专注对应的业务类(结构体)文件即可,以及极易被调整的业务执行顺序

三、代码案例

以按照多种条件查询返回查询结果为例

search.go

package orderimport ("time"
)type Option func(*Options)// Options  每次请求的上下文数据
type Options struct {OrderId    uint64UserId     uint64GoodsId    uint64ProductId  uint64MerchantId uint64PkgId      uint64Status         uint8DeliveryStatus uint8HasInvoice  stringUserNick    stringProductName stringMobilePhone stringOrderByType stringStartTime   time.TimeEndTime     time.TimePageNum     intPageSize    int
}// FilterByOrderId 按照 order_id 过滤
func FilterByOrderId(orderId uint64) Option {return func(o *Options) {o.OrderId = orderId}
}// FilterByUserId 按照 user_id 过滤
func FilterByUserId(userId uint64) Option {return func(o *Options) {o.UserId = userId}
}// FilterByGoodsId 按照 goods_id 过滤
func FilterByGoodsId(goodsId uint64) Option {return func(o *Options) {o.GoodsId = goodsId}
}// FilterByProductId 按照 product_id 过滤
func FilterByProductId(productId uint64) Option {return func(o *Options) {o.ProductId = productId}
}// FilterByMerchantId 按照 merchant_id 过滤
func FilterByMerchantId(merchantId uint64) Option {return func(o *Options) {o.MerchantId = merchantId}
}// FilterByPkgId 按照 merchant_id 过滤
func FilterByPkgId(pkgId uint64) Option {return func(o *Options) {o.PkgId = pkgId}
}// FilterByStatus 按照 status 过滤
func FilterByStatus(status uint8) Option {return func(o *Options) {o.Status = status}
}// FilterByDeliveryStatus 按照 delivery_status 过滤
func FilterByDeliveryStatus(deliveryStatus uint8) Option {return func(o *Options) {o.DeliveryStatus = deliveryStatus}
}// FilterByHasInvoice 按照 has_invoice 过滤
func FilterByHasInvoice(hasInvoice string) Option {return func(o *Options) {o.HasInvoice = hasInvoice}
}// FilterByUserNick 按照 user_nick 过滤
func FilterByUserNick(userNick string) Option {return func(o *Options) {o.UserNick = userNick}
}// FilterByProductName 按照 ProductName 过滤
func FilterByProductName(productName string) Option {return func(o *Options) {o.ProductName = productName}
}// FilterByCreateAt 按照 create_at 过滤
func FilterByCreateAt(startTime, endTime time.Time) Option {return func(o *Options) {o.StartTime = startTimeo.EndTime = endTime}
}// OrderByCreateAt 按照create_at过滤
func OrderByCreateAt(orderByType string) Option {return func(o *Options) {o.OrderByType = orderByType}
}// RecordsByPage 按照分页输出
func RecordsByPage(page, pageSize int) Option {return func(o *Options) {o.PageNum = pageo.PageSize = pageSize}
}

orders.go

package orderimport (common "backend/storage/gorm""backend/storage/gorm/model""context""fmt""gorm.io/gorm"
)var _ OrdersClient = (*ordersClient)(nil)// OrdersClient 订单客户端
type OrdersClient interface {GetDB() *gorm.DBUpdateOrdersByOrderID(ctx context.Context, updateInfo *model.Orders) errorGetSearchInfo(ctx context.Context, opts ...Option) ([]*model.Orders, error)CountByToSend(ctx context.Context, countInfo *model.StatusCount) (int, error)
}// ordersClient 订单结构体
type ordersClient struct {db *gorm.DB
}// GetDB 获取DB
func (a *ordersClient) GetDB() *gorm.DB {return a.db
}// UpdateOrdersByOrderID 按照 OrderID 过滤然后非零更新
func (o *ordersClient) UpdateOrdersByOrderID(ctx context.Context, updateInfo *model.Orders) error {return o.db.Where("order_id = ? ", updateInfo.OrderId).Updates(updateInfo).WithContext(ctx).Error
}// CountByToSend 按照未发货记录数据
func (o *ordersClient) CountByToSend(ctx context.Context, countInfo *model.StatusCount) (int, error) {statusCount := model.StatusCount{}err := o.db.Select("status, count(*) as count").Where("status = ? ", countInfo.Status).Scan(&statusCount).Errorif err != nil {return 0, err}return countInfo.Count, nil
}// GetSearchInfo 通过多项参数信息 进行数据检索
func (a *ordersClient) GetSearchInfo(ctx context.Context, opts ...Option) ([]*model.Orders, error) {var options *Optionsdb := a.dborders := make([]*model.Orders, 0)for _, opt := range opts {opt(options)}if options.OrderId != 0 {db = db.Where("order_id = ? ", options.OrderId)}if options.UserNick != "" {db = db.Where("user_nick like %?% ", options.UserNick)}if options.StartTime.IsZero() && options.EndTime.IsZero() {db = db.Where("create_at >= ? and create_at < ? ", options.StartTime, options.EndTime)}if options.Status != 0 {db = db.Where("status = ? ", options.Status)}if options.DeliveryStatus != 0 {db = db.Where("refund_status = ? ", options.DeliveryStatus)}if options.UserId != 0 {db = db.Where("user_id = ? ", options.UserId)}if options.OrderByType == common.DescendSort {db = db.Order(fmt.Sprintf("create_at %s", options.OrderByType))}if options.PageNum > 0 && options.PageSize > 0 {db = db.Limit(options.PageSize).Offset((options.PageNum - 1) * options.PageSize)}err := db.Unscoped().Find(&orders).Errorif err != nil {return nil, err}return orders, nil
}

总结

代码案例为个人编写,个人代码风格不喜勿喷, 有任何问题请与我联系。

golang 责任链模式(链式调用)相关推荐

  1. 设计模式--责任链模式--Java实现

    设计模式–责任链模式–Java实现 责任链模式–链式数据结构–内存消耗–Java的awt事件一开始用责任链模式后来改为观察者模式–为什么呢?–现在的应用–dom事件–异常处理机制-过滤器链–等等 学习 ...

  2. 最近学习了责任链模式

    2019独角兽企业重金招聘Python工程师标准>>> 前言 来菜鸟这个大家庭10个月了,总得来说比较融入了环境,同时在忙碌的工作中也深感技术积累不够,在优秀的人身边工作必须更加花时 ...

  3. 设计模式(四)OkHttp的责任链模式

    一.基本概念 1.定义 多个对象都有机会处理请求,将这些对象连成一个链,将请求沿着这条链传递,直到有对象处理为止. 2.使用场景 多个对象处理同一请求,具体哪个对象处理需要动态决定 需要指定一组对象处 ...

  4. android 链式结构,Android 架构师之路10 设计模式之责任链模式

    1. 责任链模式概念 1.1 介绍 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象.这样就实现了请求者和接受者之间的解耦,并且在客户端可以实现动态的组合职责 ...

  5. Android设计模式详解之责任链模式

    前言 责任链模式是行为型设计模式: 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 使用场景: 多 ...

  6. 责任链模式(Chain of Responsibility)

    责任链模式(Chain of Responsibility) 1.意图 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个 ...

  7. Chain of Responsibility 责任链模式 MD

    责任链模式 简介 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链,请求在这个链上[传递],直到链上的某一个对象决定处理此请求.发出这个请求的客户 ...

  8. Java 责任链模式

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为 ...

  9. 设计模式之五 责任链模式(Chain of Responsibility)

    2019独角兽企业重金招聘Python工程师标准>>> 一. 场景 相信我们都有过这样的经历: 我们去职能部门办理一个事情,先去了A部门,到了地方被告知这件事情由B部门处理: 当我们 ...

最新文章

  1. AD下批量导入域用户
  2. C++算术运算符与算术表达式
  3. jquery+javascript触发a标签的点击事件
  4. python thrift demo
  5. SAP Spartacus 4.0 版本因为 hamburger 依赖导致构建出错的问题
  6. 汇编指令的学习3——协处理器cp15的操作指令mcr、mrc
  7. 每半个小时执行一次_活动执行主要做些工作?
  8. 2020受欢迎的20个JavaScript 库
  9. Kompose: Docker-compose 到 Kubernetes 的迁移工具
  10. SQL Server 2008 R2永久激活秘钥
  11. ECharts 实现地图功能
  12. 【蓝桥杯】真题训练 2014年C++A组 题4 史丰收速算
  13. 腾讯云灯塔计划——云行业研究报告
  14. 微信小程序连接WiFi
  15. 解决redisson超时org.redisson.client.RedisResponseTimeoutException: Redis server response timeout
  16. oracle误删除数据,恢复删除的数据,删除数据后提交恢复
  17. 最全面的github pages搭建个人博客教程
  18. mt4查看虚拟服务器,查mt4服务器地址
  19. idea不用鼠标写代码
  20. 关闭VScode界面输入右上角的累加数字

热门文章

  1. 用QTP脚本操作【腾讯QQ好友买卖】
  2. VSD?啥是VSD?VSD应用场景你知道吗?
  3. Java中Set集合的使用
  4. 51单片机开发实例 基于52单片机的远程开锁系统
  5. 高级程序员的七大特征,你有几条?
  6. xfce4-session: Unable to access file /home/user/.ICEauthority: Permission denied
  7. 5分钟读懂一致性哈希算法原理
  8. 分享券商通达信下单接口执行委托下单过程
  9. @JSONField注解的使用
  10. 偏差bias与方差variance