赞
踩
我们在写golang 代码的时候经常会出现我想有一个可变参数来确认初始化变量的问题或者针对于按照多种条件查询返回查询结果。
我个人比较推崇使用责任链模式(链式调用)的方式来处理,这样的代码维护简单容易理解。
首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,然后在这一系列对象中传递请求对象,直到被处理为止。
我们从概念中可以看出责任链模式有如下明显的优势:
按职责划分:解耦
对象链:逻辑清晰
但是有一点直到被处理为止,代表最终只会被一个实际的业务对象执行了实际的业务逻辑,明显适用的场景并不多。但是除此之外,上面的那两点优势还是让人很心动,所以,为了适用于目前所接触的绝大多数业务场景,把概念进行了简单的调整,如下:
首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,直到“链路结束”为止。(结束:异常结束,或链路执行完毕结束)
简单的直到“链路结束”为止转换可以让我们把责任链模式适用于任何复杂的业务场景。
直观:一眼可观的业务调用过程
无限扩展:可无限扩展的业务逻辑
高度封装:复杂业务代码依然高度封装
极易被修改:复杂业务代码下修改代码只需要专注对应的业务类(结构体)文件即可,以及极易被调整的业务执行顺序
以按照多种条件查询返回查询结果为例
package order import ( "time" ) type Option func(*Options) // Options 每次请求的上下文数据 type Options struct { OrderId uint64 UserId uint64 GoodsId uint64 ProductId uint64 MerchantId uint64 PkgId uint64 Status uint8 DeliveryStatus uint8 HasInvoice string UserNick string ProductName string MobilePhone string OrderByType string StartTime time.Time EndTime time.Time PageNum int PageSize 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 = startTime o.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 = page o.PageSize = pageSize } }
package order import ( "context" "fmt" common "backend/storage/gorm" "backend/storage/gorm/model" "gorm.io/gorm" ) var _ OrdersClient = (*ordersClient)(nil) // OrdersClient 订单客户端 type OrdersClient interface { GetDB() *gorm.DB UpdateOrdersByOrderID(ctx context.Context, updateInfo *model.Orders) error GetSearchInfo(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). Error if err != nil { return 0, err } return countInfo.Count, nil } // GetSearchInfo 通过多项参数信息 进行数据检索 func (a *ordersClient) GetSearchInfo(ctx context.Context, opts ...Option) ([]*model.Orders, error) { var options Options db := a.db orders := 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).Error if err != nil { return nil, err } return orders, nil }
代码案例为个人编写,个人代码风格不喜勿喷, 有任何问题请与我联系。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。