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
}
简单来描述自动校验分为以下几个步骤:
- 在接收传参的转换函数中,先把本次请求传入的字段拿到,并且注册这些字段对应的校验函数。
- 进入到业务逻辑处理的函数中,再次增加一些当前业务场景需要的特殊校验函数。
- 依次执行校验函数,观察是否有报错。
热门推荐
为什么要给宠物做体检?(了解宠物身体状况的重要性及相关注意事项)
“狂犬”不用慌,哪些动物会传播?被咬伤、抓伤如何正确自救?
狂犬病暴露后,我们应该如何处理?
群晖如何组raid阵列
《中国药典》5100通则视角:钠钙玻璃与硼硅玻璃药包材分类及检测标准解析
月季养护秘籍:精准施肥,四季花开
如何增强孩子的记忆力?脑外科医生推荐的高效学习法
教师辱骂学生可以举报吗
火锅吃得对,多吃几顿又何妨!(上)
电动自行车限速25km/h,是保障安全还是限制效率的双刃剑?
耳鳴的中醫療法:傳統智慧如何應對現代健康挑戰?
尾房不等于烂尾楼,如何选择优质尾房?
张惠妹演唱会冻出鼻涕成最佳和声:娱乐工业的低温美学能走多远
带你了解新生儿Fc受体(FcRn)
甘蓝:餐桌上的多彩明星 🌱
梨什么时候种植最好?
大腿骨折康复锻炼的方法
山药怎么削皮手不会痒
工作日中午健身指南:高效训练与快速恢复的完美结合
98.高效写作的秘诀:如何避免拖延,快速完成论文?
唐朝诗人李白的《将进酒》创作背景及赏析
Pr 入门系列之九:添加过渡(上)
口苦怎么解决
简短唯美的婚礼誓言 20条婚礼告白句子
英语学术论文写作常见错误 – 英语介词
机器学习实战:从理论到实践的完整指南
汽车上的儿童安全座椅适合哪个年龄段的孩子?
喝茶的时间和适量:如何根据个人需求制定合适的饮茶计划
淀粉肠的热量高吗?营养师为你详细解析
"食"刻守护 | 塌房了?!淀粉肠到底是什么做的?