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
}
简单来描述自动校验分为以下几个步骤:
- 在接收传参的转换函数中,先把本次请求传入的字段拿到,并且注册这些字段对应的校验函数。
- 进入到业务逻辑处理的函数中,再次增加一些当前业务场景需要的特殊校验函数。
- 依次执行校验函数,观察是否有报错。
热门推荐
火影忍者中宇智波鼬的六大绝技:从天照到体术的全方位解析
为什么总是肩膀疼痛?这些问题要警惕
东兴去越南一日游攻略
《阿凡达》世界成真!我国科研团队成功打造出高亮发光植物
铝板喇叭柱:现代技术与古典美学的完美结合
美军人员薪资波动影响因素分析
心跳慢的人长寿,1分钟跳多少次最健康?
4个迹象表明你该换跑鞋了!选鞋前先看看这7个步骤
干货满满!琳琅满目的酸奶你怎么选?
北大提高3名,清华提高5名,复旦提高11名,2025QS大学排名解读
万斯:80后草根出身,耶鲁大学毕业,33岁出书,老婆是印度裔律师
“合肥造”自发光植物已量产 萤光向日葵一周销量突破一万株
12315官网投诉网贷流程全攻略
施工项目资料管理:方法与最佳实践
中国物质文化遗产名录:探寻千年古物的传奇故事
重实战求创新,大学生如何把握银发经济新机遇?北体教授:人才培养要适应社会需求
Excel中时间和数据匹配的四种方法详解
软考高级:存储系统 DAS、NAS、SAN 区别 - AI 解读
住宅厨房门对着阳台的风水影响及化解方法
都有人开始押注美联储加息了?美国10年期国债收益率“九连涨”
“3D”彩票的现在与未来?
红鲫鱼养殖方法和注意事项
科技与便利的完美结合!方便面的卷曲之谜:如何改变了我们的食用体验?
喜用神为金火土是什么意思,喜用神为金忌讳什么
千叶豆腐是健康食品吗?揭秘其营养真相与食用风险
商业项目的风险管理怎样进行有效评估?如何制定应对风险的策略和措施?
如何挑选优质土豆制作美味土豆丝
如何分析纸黄金时交易的特点?这种交易模式的优势和风险有哪些?
一文详解:如何查询专利真假、进度及信息
野钓必杀技:学会3种调平水,钓鱼调漂不纠结