数据验证
Gin 使用 validator 包进行数据验证,支持丰富的验证规则。
📋 学习目标
- 理解数据验证的重要性
- 掌握结构体标签验证
- 学会自定义验证规则
- 理解不同绑定方式
- 掌握验证错误处理
🎯 基本验证
结构体标签
go
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name" binding:"required,min=2,max=50"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"required,gte=0,lte=150"`
Password string `json:"password" binding:"required,min=6"`
}
func main() {
r := gin.Default()
r.POST("/user", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})
r.Run(":8080")
}常用验证标签
go
type User struct {
// 必需字段
Name string `binding:"required"`
// 字符串长度
Title string `binding:"min=1,max=100"`
// 数值范围
Age int `binding:"gte=0,lte=150"`
// 邮箱格式
Email string `binding:"email"`
// URL 格式
Website string `binding:"url"`
// 枚举值
Status string `binding:"oneof=pending completed cancelled"`
// 正则表达式
Phone string `binding:"regexp=^1[3-9]\\d{9}$"`
// 忽略空值
Description string `binding:"omitempty,min=0,max=500"`
}🔧 绑定方式
JSON 绑定
go
r.POST("/user", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})表单绑定
go
r.POST("/form", func(c *gin.Context) {
var user User
if err := c.ShouldBind(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})URI 绑定
go
type User struct {
ID int `uri:"id" binding:"required"`
}
r.GET("/user/:id", func(c *gin.Context) {
var user User
if err := c.ShouldBindUri(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})查询参数绑定
go
type Query struct {
Page int `form:"page" binding:"gte=1"`
PageSize int `form:"page_size" binding:"gte=1,lte=100"`
Keyword string `form:"keyword"`
}
r.GET("/search", func(c *gin.Context) {
var query Query
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, query)
})🎨 自定义验证
自定义验证函数
go
package main
import (
"github.com/go-playground/validator/v10"
"github.com/gin-gonic/gin"
)
var validate *validator.Validate
func init() {
validate = validator.New()
validate.RegisterValidation("custom_rule", customValidation)
}
func customValidation(fl validator.FieldLevel) bool {
value := fl.Field().String()
// 自定义验证逻辑
return len(value) > 5
}
type User struct {
Name string `binding:"required,custom_rule"`
}
func main() {
r := gin.Default()
r.POST("/user", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, user)
})
r.Run(":8080")
}🏃♂️ 实践应用
完整的验证示例
go
package main
import (
"github.com/gin-gonic/gin"
)
type CreateUserRequest struct {
Name string `json:"name" binding:"required,min=2,max=50"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=8"`
Age int `json:"age" binding:"gte=18,lte=100"`
}
type UpdateUserRequest struct {
Name *string `json:"name,omitempty" binding:"omitempty,min=2,max=50"`
Email *string `json:"email,omitempty" binding:"omitempty,email"`
Age *int `json:"age,omitempty" binding:"omitempty,gte=18,lte=100"`
}
func main() {
r := gin.Default()
r.POST("/users", func(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": formatValidationError(err)})
return
}
c.JSON(201, gin.H{"message": "用户创建成功"})
})
r.PUT("/users/:id", func(c *gin.Context) {
var req UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": formatValidationError(err)})
return
}
c.JSON(200, gin.H{"message": "用户更新成功"})
})
r.Run(":8080")
}
func formatValidationError(err error) string {
// 格式化验证错误
return err.Error()
}⚠️ 注意事项
1. 验证顺序
go
// 验证按标签顺序执行
type User struct {
Email string `binding:"required,email"` // 先检查必需,再检查格式
}2. 错误处理
go
// ✅ 提供友好的错误信息
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{
"error": "验证失败",
"details": err.Error(),
})
return
}3. 性能考虑
go
// ✅ 验证是同步操作,避免在验证中执行耗时操作📚 扩展阅读
⏭️ 下一章节
认证授权 → 学习 Gin 的认证和授权机制
💡 提示: 数据验证是 API 安全的基础,严格的验证可以防止无效数据和潜在的安全问题!
