当前位置: 首页 > article >正文

Java转Go日记(五十九):参数验证

1. 结构体验证

用gin框架的数据验证,可以不用解析数据,减少if else,会简洁许多。

package mainimport ("fmt""time""github.com/gin-gonic/gin"
)//Person ..
type Person struct {//不能为空并且大于10Age      int       `form:"age" binding:"required,gt=10"`Name     string    `form:"name" binding:"required"`Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}func main() {r := gin.Default()r.GET("/5lmh", func(c *gin.Context) {var person Personif err := c.ShouldBind(&person); err != nil {c.String(500, fmt.Sprint(err))return}c.String(200, fmt.Sprintf("%#v", person))})r.Run()
}

代码启动之后,示例访问地址:

http://localhost:8080/5lmh?age=11&name=枯藤&birthday=2006-01-02

2. 自定义验证

package mainimport ("net/http""reflect""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""gopkg.in/go-playground/validator.v8"
)/*对绑定解析到结构体上的参数,自定义验证功能比如我们要对 name 字段做校验,要不能为空,并且不等于 admin ,类似这种需求,就无法 binding 现成的方法需要我们自己验证方法才能实现 官网示例(https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Custom_Functions)这里需要下载引入下 gopkg.in/go-playground/validator.v8
*/
type Person struct {Age int `form:"age" binding:"required,gt=10"`// 2、在参数 binding 上使用自定义的校验方法函数注册时候的名称Name    string `form:"name" binding:"NotNullAndAdmin"`Address string `form:"address" binding:"required"`
}// 1、自定义的校验方法
func nameNotNullAndAdmin(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {if value, ok := field.Interface().(string); ok {// 字段不能为空,并且不等于  5lmhreturn value != "" && !("5lmh" == value)}return true
}func main() {r := gin.Default()// 3、将我们自定义的校验方法注册到 validator中if v, ok := binding.Validator.Engine().(*validator.Validate); ok {// 这里的 key 和 fn 可以不一样最终在 struct 使用的是 keyv.RegisterValidation("NotNullAndAdmin", nameNotNullAndAdmin)}/*curl -X GET "http://127.0.0.1:8080/testing?name=&age=12&address=beijing"curl -X GET "http://127.0.0.1:8080/testing?name=lmh&age=12&address=beijing"curl -X GET "http://127.0.0.1:8080/testing?name=adz&age=12&address=beijing"*/r.GET("/5lmh", func(c *gin.Context) {var person Personif e := c.ShouldBind(&person); e == nil {c.String(http.StatusOK, "%v", person)} else {c.String(http.StatusOK, "person bind err:%v", e.Error())}})r.Run()
}

示例2:

package mainimport ("net/http""reflect""time""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""gopkg.in/go-playground/validator.v8"
)// Booking contains binded and validated data.
type Booking struct {//定义一个预约的时间大于今天的时间CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`//gtfield=CheckIn退出的时间大于预约的时间CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
}func bookableDate(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {//field.Interface().(time.Time)获取参数值并且转换为时间格式if date, ok := field.Interface().(time.Time); ok {today := time.Now()if today.Unix() > date.Unix() {return false}}return true
}func main() {route := gin.Default()//注册验证if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//绑定第一个参数是验证的函数第二个参数是自定义的验证函数v.RegisterValidation("bookabledate", bookableDate)}route.GET("/5lmh", getBookable)route.Run()
}func getBookable(c *gin.Context) {var b Bookingif err := c.ShouldBindWith(&b, binding.Query); err == nil {c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}// curl -X GET "http://localhost:8080/5lmh?check_in=2019-11-07&check_out=2019-11-20"
// curl -X GET "http://localhost:8080/5lmh?check_in=2019-09-07&check_out=2019-11-20"
// curl -X GET "http://localhost:8080/5lmh?check_in=2019-11-07&check_out=2019-11-01"

 

3. 多语言翻译验证

当业务系统对验证信息有特殊需求时,例如:返回信息需要自定义,手机端返回的信息需要是中文而pc端发挥返回的信息需要时英文,如何做到请求一个接口满足上述三种情况。

package mainimport ("fmt""github.com/gin-gonic/gin""github.com/go-playground/locales/en""github.com/go-playground/locales/zh""github.com/go-playground/locales/zh_Hant_TW"ut "github.com/go-playground/universal-translator""gopkg.in/go-playground/validator.v9"en_translations "gopkg.in/go-playground/validator.v9/translations/en"zh_translations "gopkg.in/go-playground/validator.v9/translations/zh"zh_tw_translations "gopkg.in/go-playground/validator.v9/translations/zh_tw"
)var (Uni      *ut.UniversalTranslatorValidate *validator.Validate
)type User struct {Username string `form:"user_name" validate:"required"`Tagline  string `form:"tag_line" validate:"required,lt=10"`Tagline2 string `form:"tag_line2" validate:"required,gt=1"`
}func main() {en := en.New()zh := zh.New()zh_tw := zh_Hant_TW.New()Uni = ut.New(en, zh, zh_tw)Validate = validator.New()route := gin.Default()route.GET("/5lmh", startPage)route.POST("/5lmh", startPage)route.Run(":8080")
}func startPage(c *gin.Context) {//这部分应放到中间件中locale := c.DefaultQuery("locale", "zh")trans, _ := Uni.GetTranslator(locale)switch locale {case "zh":zh_translations.RegisterDefaultTranslations(Validate, trans)breakcase "en":en_translations.RegisterDefaultTranslations(Validate, trans)breakcase "zh_tw":zh_tw_translations.RegisterDefaultTranslations(Validate, trans)breakdefault:zh_translations.RegisterDefaultTranslations(Validate, trans)break}//自定义错误内容Validate.RegisterTranslation("required", trans, func(ut ut.Translator) error {return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details}, func(ut ut.Translator, fe validator.FieldError) string {t, _ := ut.T("required", fe.Field())return t})//这块应该放到公共验证方法中user := User{}c.ShouldBind(&user)fmt.Println(user)err := Validate.Struct(user)if err != nil {errs := err.(validator.ValidationErrors)sliceErrs := []string{}for _, e := range errs {sliceErrs = append(sliceErrs, e.Translate(trans))}c.String(200, fmt.Sprintf("%#v", sliceErrs))}c.String(200, fmt.Sprintf("%#v", "user"))
}

正确的链接:http://localhost:8080/testing?user_name=枯藤&tag_line=9&tag_line2=33&locale=zh

http://localhost:8080/testing?user_name=枯藤&tag_line=9&tag_line2=3&locale=en 返回英文的验证信息

http://localhost:8080/testing?user_name=枯藤&tag_line=9&tag_line2=3&locale=zh 返回中文的验证信息

查看更多的功能可以查看官网 gopkg.in/go-playground/validator.v9

http://www.lryc.cn/news/2402774.html

相关文章:

  • 机器学习与深度学习14-集成学习
  • MySQL数据库表设计与索引优化终极指南
  • 【论文阅读笔记】万花筒:用于异构多智能体强化学习的可学习掩码
  • 负载均衡LB》》HAproxy
  • Vue 中组件命名与引用
  • UE 5 和simulink联合仿真,如果先在UE5这一端结束Play,过一段时间以后**Unreal Engine 5** 中会出现显存不足错误
  • 在uni-app中如何从Options API迁移到Composition API?
  • Rust 控制流
  • 【Linux基础知识系列】第十三篇-Cron与定时任务管理
  • Visual Studio 中的 MD、MTD、MDD、MT 选项详解
  • Python 3.11.9 安装教程
  • 【各种主流消息队列(MQ)对比指南】
  • PySpark、Plotly全球重大地震数据挖掘交互式分析及动态可视化研究
  • 代码训练LeetCode(24)数组乘积
  • 如何让AI自己检查全文?使用OCR和LLM实现自动“全文校订”(可DIY校订规则)
  • volka 25个短语动词
  • Java观察者模式深度解析:构建松耦合事件驱动系统的艺术
  • DFT测试之TAP/SIB/TDR
  • 【推荐算法】DeepFM:特征交叉建模的革命性架构
  • C#报错 iText.Kernel.Exceptions.PdfException: ‘Unknown PdfException
  • 数据库表中「不是 null」的含义
  • Elasticsearch的搜索流程描述
  • Visual Studio问题记录
  • GNSS终端授时方式-合集:PPS、B码、NTP、PTP、单站授时,共视授时
  • 5.2 HarmonyOS NEXT应用性能诊断与优化:工具链、启动速度与功耗管理实战
  • 从EDR到XDR:终端安全防御体系演进实践指南
  • 重启路由器ip不变怎么回事?原因分析与解决方法
  • 实践篇:利用ragas在自己RAG上实现LLM评估②
  • 【CVE-2025-4123】Grafana完整分析SSRF和从xss到帐户接管
  • 高精度滚珠导轨在医疗设备中的多元应用场景