Gin 使用 validator 库进行参数验证,通过结构体标签定义验证规则。
在 binding 标签中添加验证规则:
type User struct {
Name string `binding:"required"`
Email string `binding:"required,email"`
Age int `binding:"required,gte=0,lte=150"`
}
| 规则 | 说明 |
|---|---|
required | 必填 |
min=3 | 最小长度 |
max=20 | 最大长度 |
len=10 | 固定长度 |
email | 邮箱格式 |
url | URL 格式 |
uri | URI 格式 |
alpha | 只含字母 |
alphanum | 字母和数字 |
numeric | 数字 |
hexadecimal | 十六进制 |
uuid | UUID 格式 |
json | JSON 格式 |
oneof=red green blue | 枚举值 |
| 规则 | 说明 |
|---|---|
eq=10 | 等于 |
ne=0 | 不等于 |
gt=0 | 大于 |
gte=0 | 大于等于 |
lt=100 | 小于 |
lte=100 | 小于等于 |
| 规则 | 说明 |
|---|---|
eqfield=Password | 等于另一字段 |
nefield=OldPassword | 不等于另一字段 |
gtfield=StartDate | 大于另一字段 |
gtefield=StartDate | 大于等于另一字段 |
type LoginRequest struct {
Username string `binding:"required"`
Password string `binding:"required"`
}
r.POST("/login", func(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBind(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "登录成功"})
})
type RegisterRequest struct {
Username string `binding:"required,min=3,max=20"`
Password string `binding:"required,min=6,max=32"`
}
r.POST("/register", func(c *gin.Context) {
var req RegisterRequest
if err := c.ShouldBind(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "注册成功"})
})
type SubscribeRequest struct {
Email string `binding:"required,email"`
}
r.POST("/subscribe", func(c *gin.Context) {
var req SubscribeRequest
if err := c.ShouldBind(&req); err != nil {
c.JSON(400, gin.H{"error": "无效的邮箱地址"})
return
}
c.JSON(200, gin.H{"message": "订阅成功"})
})
type FilterRequest struct {
Status string `binding:"required,oneof=active inactive pending"`
Sort string `binding:"oneof=asc desc"`
}
r.GET("/items", func(c *gin.Context) {
var req FilterRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"status": req.Status, "sort": req.Sort})
})
type ChangePasswordRequest struct {
OldPassword string `binding:"required,min=6"`
NewPassword string `binding:"required,min=6"`
ConfirmPassword string `binding:"required,eqfield=NewPassword"`
}
r.POST("/password", func(c *gin.Context) {
var req ChangePasswordRequest
if err := c.ShouldBind(&req); err != nil {
c.JSON(400, gin.H{"error": "两次密码输入不一致"})
return
}
c.JSON(200, gin.H{"message": "密码修改成功"})
})
type Pagination struct {
Page int `form:"page" binding:"required,gte=1"`
PageSize int `form:"page_size" binding:"required,gte=1,lte=100"`
}
r.GET("/list", func(c *gin.Context) {
var p Pagination
if err := c.ShouldBindQuery(&p); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"page": p.Page, "page_size": p.PageSize})
})
使用 binding:"-" 跳过验证:
type User struct {
Name string `binding:"required"`
Bio string `binding:"-"`
}
结合 omitempty 使用:
type UpdateUser struct {
Name string `binding:"omitempty,min=3"`
Email string `binding:"omitempty,email"`
}
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type CreateUserRequest struct {
Username string `json:"username" binding:"required,min=3,max=20,alphanum"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=8,max=32"`
Age int `json:"age" binding:"required,gte=1,lte=150"`
Role string `json:"role" binding:"required,oneof=admin user guest"`
}
type UpdateUserRequest struct {
Username string `json:"username" binding:"omitempty,min=3,max=20,alphanum"`
Email string `json:"email" binding:"omitempty,email"`
Age int `json:"age" binding:"omitempty,gte=1,lte=150"`
}
func main() {
r := gin.Default()
r.POST("/users", createUser)
r.PATCH("/users/:id", updateUser)
r.Run(":8080")
}
func createUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "用户创建成功",
"username": req.Username,
})
}
func updateUser(c *gin.Context) {
id := c.Param("id")
var req UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"id": id,
"message": "用户更新成功",
})
}
这一章学习了: