从 PHP 到 AI + Golang,程序员自救转型手记(四十三):前后端数据验证

这是一个系列 Blog,作者将以一个 PHP 全栈工程师的身份,利用 AI 工具(claude code、codex、deepseek、豆包等):从零开始学习 golang 语言,并最终完成 ai-go-admin(github | gitee)开源项目的制作,全程记录分享。

在上一期,我们进行了 "前端表格组件",本期将完成:前后端数据验证

前后端数据验证

服务端数据验证

服务端一共有三种数据验证方案:

方案一

模型层写 binding tag,然后在控制器层使用 ginShouldBindJSON,在绑定 JSON 数据同时完成效验(基控制器默认的 CreateUpdate 方法都已经调过 ShouldBindJSON 了,模型定义写好验证规则即可)示例如下:

go 复制代码
Username string `gorm:"comment:用户名;type:varchar(64);not null" binding:"required"`

required 规则意为 必填,完整可用规则有很多,可以参考:go-playground/validator | gin 模型绑定和验证章节

go-playground/validator 包已随 gin 框架内置,可直接使用。

方案二

模型定义写 validate tag,如:

go 复制代码
Username string `gorm:"comment:用户名;type:varchar(64)" validate:"required"`

可用规则和 方案一binding 一致,validate 的写法是 go-playground/validator 原生提供的。

然后,服务层或控制器层重写 CreateUpdate 等方法手动完成效验,示例如下:

go 复制代码
type User struct {
    FirstName string `validate:"required"`
    Age       uint8  `validate:"gte=0,lte=130"`
    Email     string `validate:"required,email"`
}

validate := validator.New()

user := &User{
    Age:   135,
    Email: "Badger.Smith@gmail.com",
}

err := validate.Struct(user)

方案三

增加 DTO,并定义以上的 binding / validate tag,然后重写控制器/服务,AdminUpdateRequest 就是一个自定义 DTO,不理解的可以全局搜索参考。

何时在控制器效验,何时在服务层效验?

服务层:涉及数据库、父子关系、唯一性、字段联动的校验。

控制器层:只校验字段自身独立规则,如必填、长度、有效值,不依赖数据库、不跨字段判断。

例如 AdminRule 表title、name、type 的必填就应该放在控制器层,name 的重复、pid 不能是自身,就应该放在服务层;注意仓储层不做任何效验,仅使用 not null、唯一索引等兜底即可。

前端数据验证

前端主要是表单数据的验证,我们准备了一个验证工具包 src\utils\validate.ts,里边定义了各种验证规则,另外主要是导出了一个验证规则构建器:buildValidatorRule 函数,它可以非常方便的生成 el-form 表单的常用验证规则,示例如下:

element plus 的表单验证,是基于 async-validator

vue 复制代码
<template>
    <div>
        <el-form ref="formRef" :model="formItems" :rules="rules"></el-form>
    </div>
</template>

<script setup lang="ts">
import { regularPassword, buildValidatorRule } from '/@/utils/validate'
import type { FormItemRule } from 'element-plus'

const rules: Partial<Record<string, FormItemRule[]>> = reactive({
    username: [buildValidatorRule({ name: 'required', title: '用户名' }), buildValidatorRule({ name: 'account' })],
    nickname: [buildValidatorRule({ name: 'required', title: '昵称' })],
    email: [buildValidatorRule({ name: 'email', message: '邮箱错误' })],
    mobile: [buildValidatorRule({ name: 'mobile', message: '手机号错误' })],
    password: [
        {
            validator: (rule: any, val: string, callback: Function) => {
                if (props.manager.form.operate == 'create') {
                    if (!val) {
                        return callback(new Error('密码必填'))
                    }
                } else {
                    if (!val) {
                        return callback()
                    }
                }
                if (!regularPassword(val)) {
                    return callback(new Error('密码需要 6-32 位,禁止使用特殊符号'))
                }
                return callback()
            },
            trigger: 'blur',
        },
    ],
})
</script>
相关推荐
步行cgn3 分钟前
MyBatis 错误 Result Maps collection does not contain value for ... 详解与解决方案
后端
用户250694921616 分钟前
Cordis 从入门到实战:插件卸载后,别留下一地鸡毛
后端
SomeB1oody19 分钟前
【RustyML入门】5.3. 聚类指标
开发语言·后端·机器学习·rust·教程
天空之城--25 分钟前
高效使用 Claude Code 开发 Web3D 程序的系统化方法论
ai编程
IT_陈寒32 分钟前
Vite打包给我挖的这个坑,差点搞崩我的项目
前端·人工智能·后端
【赫兹威客】浩哥41 分钟前
基于SpringBoot+Vue3的企业办公自动化OA系统|集成Activiti工作流引擎
spring boot·后端·课程设计
旗开得胜马到成功1 小时前
AI编程智能体删库后,我把开发环境从每日备份换成中科热备CDP秒级回滚
大数据·elasticsearch·ai编程
卷无止境1 小时前
LiteLLM 全面解析开源AI网关如何统一管理百余种大模型
后端·python
__zRainy__1 小时前
Node系列 · Node基础:https 模块
后端·网络协议·http·https·node.js
ADRU1 小时前
深度拆解DeepSeek Harness插件热更新实现原理
人工智能·ai·ai编程