Go-Gin中优雅的实现参数校验,自定义错误消息提示

问题描述

在参数校验的时候我们一般会基于"github.com/go-playground/validator/v10"这个库给结构体加标签实现校验参数,当参数校验错误的时候,他的提示一般是英文的,怎么自定义参数错误提示呢?跟着我一步步来

注册校验器

package initializeimport ("ToDoList/global""ToDoList/model/request""ToDoList/util/validate""github.com/gin-gonic/gin/binding""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator"v10 "github.com/go-playground/validator/v10"zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)func RegisterValidator[T interface{}](fn v10.StructLevelFunc, model T) {translator := zh.New()universalTransator := ut.New(translator, translator)global.GVA_TRANS, _ = universalTransator.GetTranslator("zh")if v, ok := binding.Validator.Engine().(*v10.Validate); ok {v.RegisterStructValidation(fn, model)_ = zhTranslations.RegisterDefaultTranslations(v, global.GVA_TRANS)}}type _Validator struct{}func (receiver _Validator) InitValidator() {RegisterValidator[request.Login](validate.UserLoginValidate.Validation, request.Login{})
}var Validator = new(_Validator)func (receiver *ginEngine) InitEngine() *gin.Engine {r := gin.Default()// 这里进行注册校验器!!Validator.InitValidator()return r
}

定义接口

我们定义一个接口规范,利于代码维护

package validateimport "github.com/go-playground/validator/v10"type Validation interface {CreateValidate() validator.StructLevelFunc
}

定义具体参数校验的方法

ReportError函数第四个参数Param将作为错误时消息提示。

package validateimport ("ToDoList/model/request""github.com/go-playground/validator/v10""reflect"
)type userLoginValidate struct{}func (receiver userLoginValidate) CreateValidate() validator.StructLevelFunc {return func(sl validator.StructLevel) {user := sl.Current().Interface().(request.Login)StructNotEmpty(sl, user, []string{})if !VerifyPassword(8, 16, user.Password) {sl.ReportError(reflect.ValueOf(user.Password), "", "", "", "密码要出现数字、大写字母、小写字母、特殊字符(.@$!%*#_~?&^),至少包含其中2种且长度在8-16之间")}}
}var UserLoginValidate = new(userLoginValidate)

定义公共函数

1.定义一个翻译的函数

func CustomErrMessage(err error) string {var result stringerrors := err.(validator.ValidationErrors)for _, err := range errors {if err.Param() != "" {result += err.Param() + ","}}return result
}

2.判断结构体字段是否为空

// 结构体字段判断是否为空
func StructNotEmpty(sl validator.StructLevel, st interface{}, omitKeys []string) {t := reflect.TypeOf(st)if t.Kind() == reflect.Ptr {t = t.Elem()}if t.Kind() != reflect.Struct {fmt.Println("必须传入结构体才能判断是否字段为空")return}v := reflect.ValueOf(st) //获取reflect.Type类for i := 0; i < v.NumField(); i++ {if !slices.Contains(omitKeys, t.Field(i).Name) {label := t.Field(i).Tag.Get("label")value := v.Field(i).Interface().(string)if len(value) == 0 {sl.ReportError(t.Field(i), "", "", "", fmt.Sprintf("%s不能为空", label))}}}
}

结构体标签

label标签是结构体字段的中文翻译,以便于当结构体字段为空时StructNotEmpty函数可以进行翻译。

type Login struct {Username  string `json:"username" binding:"required,min=4,max=16" label:"用户名"` // 用户名Password  string `json:"password" binding:"required,min=8,max=16" label:"密码"`  // 密码Captcha   string `json:"captcha" binding:"required" label:"验证码"`               // 验证码CaptchaId string `json:"captchaId" binding:"required" label:"验证码ID"`           // 验证码ID
}

返回结果

func (receiver *userApi) Login(c *gin.Context) {// 1.绑定用户表单数据var loginForm request.Login// 2.检验用户登录表单if err := c.ShouldBindJSON(&loginForm); err != nil {response.Response.FailWithMessage(validate.CustomErrMessage(err), c)return}
}

结果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

  1. 先在Gin中注册验证器
  2. 定义校验函数并通过sl validator.StructLevel调用sl.ReportError传入param参数作为自定义错误
  3. 然后绑定结构体 var loginForm request.Login if err := c.ShouldBindJSON(&loginForm);
  4. 当绑定失败的时候把err传给CustomErrMessage函数CustomErrMessage函数,将会把param的值作为错误结果
  5. 然后将CustomErrMessage函数返回结果给客户端即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/600746.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024/4/1—力扣—两数相除

代码实现&#xff1a; 思路&#xff1a;用减法模拟除法 // 用减法模拟除法 int func(int a, int b) { // a、b均为负数int ans 0;while (a < b) { // a的绝对值大于等于b&#xff0c;表示此时a够减int t b;int count 1; // 用来计数被减的次数// t > INT_MIN / 2:防止…

鸿蒙实现一种仿小红书首页滑动联动效果

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 效果描述&#xff1a;通过手指滑动列表&#xff0c;控制位置显示效果为&#xff1a;不论列表在什么位置下滑时下图粉色位置布局显示&#xff0c;手指上滑时下图粉色位置布局隐藏。 效果&#xff1a; 原理分析&…

怎样恢复已删除的照片?教你3个方法,一键恢复!

很多人喜欢以拍照的形式记录生活&#xff0c;手机里的照片就很容易堆积成山&#xff0c;但当内存不够用时就不得不选择删除。可是这些美好的照片始终是很多人心中抹不去的记忆&#xff0c;那么该怎样恢复已删除的照片呢&#xff1f;下面几招&#xff0c;教你一键恢复&#xff0…

YOLOV8注意力改进方法:DoubleAttention(附代码)

原论文地址&#xff1a;原论文地址 DoubleAttention网络结构的优点在于&#xff0c;它能够有效地捕获图像中不同位置和不同特征的重要性&#xff0c;从而提高了图像识别和分割的性能。 论文相关内容介绍&#xff1a; 论文摘要&#xff1a;学习捕捉远程关系是图像/视频识别的…

Android Studio学习16——Activity跳转时的参数传递

传递数据——example 传递对象类型的数据——example 传递 接收 回传数据——example

【C++】1957. 求三个数的平均数

问题&#xff1a;1957. 求三个数的平均数 类型&#xff1a;基本运算、小数运算 题目描述&#xff1a; 小雅刚刚考完语文、数学、英语的三门期中考试&#xff0c;她想请你编个程序来帮她算算她的平均分。 要求输入三个正整数&#xff0c;分别表示三科考试的分数&#xff0c;输…

vue+springboot多角色登录

①前端编写 将Homeview修改为manager Manager&#xff1a; <template><div><el-container><!-- 侧边栏 --><el-aside :width"asideWidth" style"min-height: 100vh; background-color: #001529"><div style"h…

软件库V1.2版本开源-首页UI优化

iAppV3源码&#xff0c;首页的分类更换成了标签布局&#xff0c;各位可以参考学习&#xff0c;界面名称已经中文标注&#xff01; 老版本和现在的版本还是有较大的区别的&#xff0c;建议更新一下&#xff01; 新版本改动界面如下&#xff1a; 1、首页.iyu&#xff1a;分类按…

【Vue】Vue3中的OptionsAPI与CompositionAPI

文章目录 OptionsAPICompositionAPI对比总结 OptionsAPI 中文名:选项式API通过定义methods,computed,watch,data等属性方法&#xff0c;处理页面逻辑。以下是OptionsAPI代码结构 实例代码: <script lang"ts">// js或者tsimport { defineComponent } from vu…

LeetCode第十五题:三数之和【15/1000 python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

【安全工具】信息收集——ENScan_GO

1.初次使用 运行命令生成配置文件 ./enscan -v 2.配置cookie 参考介绍 wgpsec/ENScan_GO: 一款基于各大企业信息API的工具&#xff0c;解决在遇到的各种针对国内企业信息收集难题。一键收集控股公司ICP备案、APP、小程序、微信公众号等信息聚合导出。 (github.com) 3.友情提…

SAP ERP 公有云有哪些模块?

随着全球化竞争的加剧和企业管理需求的日益复杂化&#xff0c;越来越多的企业开始采用云端企业资源计划&#xff08;ERP&#xff09;系统来优化业务流程。SAP ERP 公有云&#xff08;SAP S/4HANA Cloud, public edition&#xff09;作为一款领先的云端ERP解决方案&#xff0c;为…