参数校验

Gin 的绑定能力可以配合 binding 标签做基础校验。

一、required 必填

type CreateUserRequest struct {
	Name string `json:"name" binding:"required"`
	Age  int    `json:"age" binding:"required"`
}

处理函数:

func createUser(c *gin.Context) {
	var req CreateUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{
			"message": "参数校验失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(201, gin.H{"data": req})
}

如果请求没有传 name,会返回校验错误。

二、常用校验规则

type RegisterRequest struct {
	Username string `json:"username" binding:"required,min=3,max=20"`
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=8"`
	Age      int    `json:"age" binding:"gte=0,lte=120"`
}

常见规则:

规则含义
required必填
min=3最小长度或最小值
max=20最大长度或最大值
email邮箱格式
gte=0大于等于 0
lte=120小于等于 120

Gin 底层使用的是 go-playground/validator,所以规则写法来自这个校验器。

三、数字零值的注意点

type Request struct {
	Age int `json:"age" binding:"required"`
}

如果前端传:

{
  "age": 0
}

0int 的零值,某些校验场景下会被认为没有值。

如果业务需要区分“没传”和“传了 0”,可以使用指针:

type Request struct {
	Age *int `json:"age" binding:"required"`
}

判断:

if req.Age != nil {
	// 使用 *req.Age 取出真实值
}

这也是 Go 指针在接口参数里的常见用途。

四、返回更友好的错误

直接返回 err.Error() 对前端不太友好。

入门阶段可以先这样封装:

func badRequest(c *gin.Context, message string) {
	c.JSON(400, gin.H{
		"code":    400,
		"message": message,
	})
}

使用:

if err := c.ShouldBindJSON(&req); err != nil {
	badRequest(c, "请求参数不正确")
	return
}

后续项目变复杂后,再统一处理校验错误的字段名和中文提示。