Go语言中 validation 库不能校验零值问题
Go语言中 validation 库不能校验零值问题
在使用Go语言的Gin框架进行Web开发时,经常会遇到参数校验的问题。本文将介绍在使用validator库进行参数校验时遇到的一个常见问题:当字段值为零值时,validator无法正确校验。通过一个具体的代码示例,我们将展示这个问题的产生原因,并提供一个简单有效的解决方案。
问题描述
在使用Gin框架处理前后端数据传递时,通常会使用ShouldBindJSON
方法将前端传来的JSON格式数据绑定到结构体中。为了确保数据的完整性,我们会在结构体中使用validator
库进行参数校验。例如:
type User struct {
Name string `json:"name" binding:"required" example:"kkk"`
Age int `json:"age" binding:"required" example:"18"`
Status int `json:"status" binding:"required" example:"1"`
}
我们规定前端传递的参数中,name
、age
、status
参数都为必填。然后在Handler
函数中使用ShouldBindJSON
绑定参数:
func handlerT(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
fmt.Println(err)
c.JSON(400, gin.H{"msg": "参数错误" + err.Error()})
return
}
}
完整代码如下:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name" binding:"required" example:"kkk"`
Age int `json:"age" binding:"required" example:"18"`
Status int `json:"status" binding:"required" example:"1"`
}
func handlerT(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
fmt.Println(err)
c.JSON(400, gin.H{"msg": "参数错误" + err.Error()})
return
}
c.JSON(200, gin.H{"msg": "ok", "data": user})
}
func main() {
r := gin.Default()
r.POST("/user", handlerT)
// 监听
err := r.Run(":9090")
if err != nil {
panic(err.Error())
}
}
使用Postman调试接口时发现,当status
值为0时,参数校验就会不通过:
解决方法
这个问题的原因在于Go语言会给结构体中没有赋值的字段赋予零值(例如,int类型的零值是0,string类型的零值是空字符串)。当标签写成required
时,如果传递零值,validator
校验时会认为没有传递这个字段,从而报错。
解决方法很简单:将int
类型改为*int
类型,使用int的指针类型。因为int指针类型的零值是nil
,这样就可以正常绑定参数了。修改后的结构体如下:
type User struct {
Name string `json:"name" binding:"required" example:"kkk"`
Age int `json:"age" binding:"required" example:"18"`
Status *int `json:"status" binding:"required" example:"1"`
}
再次使用Postman调试,可以看到参数已经成功绑定:
但是,使用指针类型后,后续处理中需要特别注意。例如,如果需要判断user.Status
是否为0,不能直接使用user.Status == 0
,因为user.Status
是指针类型,需要使用*user.Status == 0
或者先将指针类型转换为int类型再进行比较。
总结
当遇到validator
库无法校验零值的问题时,可以将数据类型改为对应的指针类型。但是,在后续逻辑处理中,不能直接使用这个指针类型的值进行常规运算,需要通过解引用或类型转换来处理。