Golang Model 字段自动化校验设计
创作时间:
作者:
@小白创作中心
Golang Model 字段自动化校验设计
引用
CSDN
1.
https://m.blog.csdn.net/weixin_42678507/article/details/145653275
在日常开发中,参数校验是一个不可避免的环节。当需要校验的字段非常多且存在耦合关系时,手写校验逻辑变得低效且难以维护。本文基于DDD领域模型设计的思想,提供了一种自动化的模型字段校验方案,通过定义Validator结构体和相关方法,实现了对模型字段的自动化校验。
背景
在我们日常开发中,不可避免的总要去进行各种参数校验,但是如果在某个场景中,要校验的字段非常多,并且在其中还有耦合关系,那么我们手写校验逻辑就变得非常的低效且难以维护。本篇文档就基于 DDD 领域模型设计的思想下,提供自动化的校验模型字段。
常见的字段校验方式
数据校验在业务逻辑代码中有着至关重要的作用,关系到整个后续业务是否可以正常运行。对参数的校验根据其具体业务逻辑与场景,可以分为字段校验、依赖校验、功能校验与逻辑校验四个部分。
字段校验
字段校验是最常见的校验类型。例如:商品名称不能超过多少个字符,商品状态必须是有效等。
func (e *Shop) ValidateShopName() error {
if e.Name != nil && e.Name == "" {
return errors.New("商品名称不能为空。")
}
if e.Name != nil && utf8.RuneCountInString(e.Name) > constant.MaxShopNameLength {
return errors.Errorf("商品名称长度为 %d, 不能超过 %d ", utf8.RuneCountInString(e.Name), constant.MaxShopNameLength)
}
return nil
}
依赖校验
依赖校验,顾名思义是在业务逻辑中依赖了其他模块。例如,在创建商品信息时,要校验一下商品依赖的商家或供应商等信息是否合法。
func (e *Shop) ValidateMerchant() error {
// 在此方法中可能需要进行外部调用或者查询 DB 的操作。
if e.HasInvalidMerchant() {
return errors.New("商家信息存在异常")
}
return nil
}
功能校验
功能校验例如用户是否有权限发布商品、商品信息是否与其他商品存在冲突等。
func (e *Shop) ValidateUserPermission() error {
if e.UserCreateShopWithoutPermission() {
return errors.New("用户无权限创建商品")
}
return nil
}
逻辑校验
逻辑校验主要是一些具体的业务逻辑。例如在下架商品时,校验是否有新用户下单等。
func (e *Shop) ValidateCloseShop() error{
if e.InvalidShopStatus() {
return errors.New("商品已下架")
}
if e.ExistShopTicket() {
return errors.New("有正在进行的订单信息,无法下架")
}
return nil
}
上面我们列出来常见的四种校验方式,当我们在一个复杂且庞大的业务场景需要把各种各样的校验放在一起去校验时,我们不得不编写一个庞大的校验函数,把这些单点的校验函数聚合起来,更有甚者都没有进行子逻辑校验的函数区分,就是第一个大函数,把各种各样的校验逻辑代码写到一个函数中,那么长此以往,校验逻辑就会非常复杂,无法迭代。
func (e *Shop) ValidateCreateShop() error {
if err = e.ValidateShopName(); err != nil {
return err
}
if err = e.ValidateDescrption(); err != nil {
return err
}
if err = e.ValidateImage(); err != nil {
return err
}
if err = e.ValidateMerchant(); err != nil {
return err
}
if err = e.ValidateUserPermission(); err != nil {
return err
}
if err = e.ValidateCloseShop(); err != nil {
return err
}
return nil
}
自动化校验
type Validator struct {
FieldNames []string // 需要更新的字段
ValidateNames []string // 需要校验的字段列表
ValidateFuncList []Func() error // 校验函数列表
}
func (v *Validator) Validate() error {
for _, validate := range v.validateFuncList {
if err := validate(); err != nil {
return err
}
}
return nil
}
// GetFields2ValidateFuncMap 各个字段的校验函数在这里扩展,在调用 register 函数时,会自动注册
func (a *Aggregate) GetFields2ValidateFuncMap() map[string]func() error {
return map[string]func() error {
constant.ShopForCreate: a.Shop.ValidateCreateShop,
constant.ShopForUpdate: a.Shop.ValidateUpdateShop,
constant.ShopCanStart: a.Shop.CanStart,
// ... 等等各种校验都可以在这里定义一个聚合函数列表
}
}
func DTOToAgg(dto *DTO.Shop) (*shop.Aggregate, error) {
baseShop := base.NewBaseShop()
// 先把传参 model 转化成领域数据
if err = copier.Copy(baseShop, dto); err != nil {
return nil, errors.Wrap(err, err.Error())
}
// New 一个聚合类
shopAgg := shop.NewShopAggregate(baseShop)
// 获取本次传给领域对象的字段,以及加载要校验的字段
setFields := GetSetOptionalFields(*dto)
var validateName []string
for _, field := range setFields {
validateName = append(validateName, field)
}
shopAgg.SetUpdateFields(setFields)
// 注册 validate 函数
shopAgg.RegisterValidator(validateName)
return shopAgg, nil
}
// 执行校验函数
func (v *Validator) ValidateMultipleFields(ctx context.Context) error {
for _, validate := range v.validateFuncList {
if err := validate(); err != nil {
return err
}
}
return
}
简单来描述自动校验分为以下几个步骤:
- 在接收传参的转换函数中,先把本次请求传入的字段拿到,并且注册这些字段对应的校验函数。
- 进入到业务逻辑处理的函数中,再次增加一些当前业务场景需要的特殊校验函数。
- 依次执行校验函数,观察是否有报错。
热门推荐
FLAC3D 6.0边界条件详解:应力边界与位移边界的设置方法
华人诺奖得主崔琦:从农村娃到科学巨匠的成长之路
培训讲师发展前景怎么样?
真石漆外立面:做出「石材」高级质感
永嘉之乱:西晋皇室的悲剧与历史的教训
淡季不淡旅游市场尽显活跃 银发人群成出游主力消费更多元
最大规模中药治疗脑出血的随机对照临床试验登上《柳叶刀》,结果令人惊讶
全球洞察|公司治理改革为亚洲股市提供额外推动力
为癫痫患者提供的职业选择与工作环境建议
成都中专助学金申请条件和流程详解
文创“小产品”催生“大产业”
癫痫患者可以选择什么职业
“天”字的演变历程:从甲骨文到现代汉字
掌握种子发芽的内部与外部条件,助力植物生长。
工程项目信息管理要点有哪些
报关公司资质要求是什么?介绍报关公司资质要求的内容和标准
射频与微波技术详解:从基本原理到核心应用的深度剖析
2026年考研择校指南:明确目标,精准定位你的学术与职业之路
如何预测答辩中的常见问题?提早准备有备无患
一张刮刮乐彩票的“生命周期”有多长?
老捷达前卫通病:问题分析与解决方案
非法挖沙构成什么罪
河南鹤壁:以城市数智化底座赋能未来——激活时空数据
全国爱国卫生月:防控儿童肥胖,从正确体重管理做起!
模拟集成电路设计系列博客——9.1 比较器
浙大团队首创白血病治疗“加强版”方案
全民k歌耳返功能怎么启用 全民K歌设置耳机耳返方法分享
高铁票价为什么不一样?
银行卡每日限额怎么改,1文学会修改银行卡每日限额
培训费不退怎么协商退款