Validator 验证
Validator 是 Go 语言最流行的数据验证库,支持结构体标签验证。
📋 学习目标
- 理解数据验证的重要性
- 掌握 Validator 的基本使用
- 学会使用验证标签
- 理解自定义验证规则
- 掌握错误处理
- 了解验证最佳实践
🎯 Validator 简介
为什么选择 Validator
- 功能强大: 支持丰富的验证规则
- 易于使用: 结构体标签验证
- 性能优秀: 编译时优化
- 扩展性强: 支持自定义验证器
- 文档完善: 官方文档详细
安装 Validator
bash
go get github.com/go-playground/validator/v10🚀 快速开始
基本使用
go
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"required,min=2,max=50"`
Email string `validate:"required,email"`
Age int `validate:"required,gte=0,lte=150"`
Password string `validate:"required,min=8"`
}
func main() {
validate := validator.New()
user := User{
Name: "张三",
Email: "zhangsan@example.com",
Age: 25,
Password: "password123",
}
if err := validate.Struct(user); err != nil {
fmt.Printf("验证失败: %v\n", err)
return
}
fmt.Println("验证成功")
}📝 验证标签
字符串验证
go
type User struct {
Name string `validate:"required"` // 必需
Email string `validate:"email"` // 邮箱格式
URL string `validate:"url"` // URL 格式
Phone string `validate:"numeric,len=11"` // 数字,长度11
Username string `validate:"alphanum,min=3,max=20"` // 字母数字,3-20字符
}数值验证
go
type Product struct {
Price float64 `validate:"required,gt=0"` // 大于0
Discount int `validate:"gte=0,lte=100"` // 0-100
Stock int `validate:"min=0"` // 最小0
Rating float64 `validate:"min=0,max=5"` // 0-5
}切片和数组验证
go
type Order struct {
Items []string `validate:"required,min=1"` // 至少1个元素
Tags []string `validate:"dive,required"` // 每个元素必需
IDs []int `validate:"dive,min=1"` // 每个元素最小1
}嵌套结构体验证
go
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Zip string `validate:"required,len=6"`
}
type User struct {
Name string `validate:"required"`
Address Address `validate:"required"`
}🔧 自定义验证
自定义验证函数
go
package main
import (
"github.com/go-playground/validator/v10"
"strings"
)
func validatePassword(fl validator.FieldLevel) bool {
password := fl.Field().String()
// 至少包含一个大写字母
hasUpper := false
// 至少包含一个小写字母
hasLower := false
// 至少包含一个数字
hasNumber := false
for _, char := range password {
switch {
case 'A' <= char && char <= 'Z':
hasUpper = true
case 'a' <= char && char <= 'z':
hasLower = true
case '0' <= char && char <= '9':
hasNumber = true
}
}
return hasUpper && hasLower && hasNumber
}
func main() {
validate := validator.New()
// 注册自定义验证器
validate.RegisterValidation("strong_password", validatePassword)
type User struct {
Password string `validate:"required,strong_password"`
}
user := User{Password: "Password123"}
if err := validate.Struct(user); err != nil {
fmt.Printf("验证失败: %v\n", err)
} else {
fmt.Println("验证成功")
}
}自定义错误消息
go
func customErrorMessages(err error) map[string]string {
errors := make(map[string]string)
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
field := fieldError.Field()
tag := fieldError.Tag()
switch tag {
case "required":
errors[field] = field + " 是必需的"
case "email":
errors[field] = field + " 必须是有效的邮箱地址"
case "min":
errors[field] = field + " 长度不能小于 " + fieldError.Param()
case "max":
errors[field] = field + " 长度不能大于 " + fieldError.Param()
default:
errors[field] = field + " 验证失败"
}
}
}
return errors
}🏃♂️ 实践应用
在 Gin 中使用
go
package main
import (
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"net/http"
)
type CreateUserRequest 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=8"`
}
func main() {
r := gin.Default()
r.POST("/users", func(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
// 处理验证错误
if validationErrors, ok := err.(validator.ValidationErrors); ok {
errors := make(map[string]string)
for _, fieldError := range validationErrors {
errors[fieldError.Field()] = getErrorMessage(fieldError)
}
c.JSON(http.StatusBadRequest, gin.H{"errors": errors})
return
}
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "用户创建成功"})
})
r.Run(":8080")
}
func getErrorMessage(fieldError validator.FieldError) string {
switch fieldError.Tag() {
case "required":
return "该字段是必需的"
case "email":
return "必须是有效的邮箱地址"
case "min":
return "长度不能小于 " + fieldError.Param()
case "max":
return "长度不能大于 " + fieldError.Param()
case "gte":
return "值不能小于 " + fieldError.Param()
case "lte":
return "值不能大于 " + fieldError.Param()
default:
return "验证失败"
}
}⚠️ 注意事项
1. 验证顺序
go
// 验证按标签顺序执行
type User struct {
Email string `validate:"required,email"` // 先检查必需,再检查格式
}2. 性能考虑
go
// ✅ 复用 validator 实例
validate := validator.New()
// ❌ 不要每次都创建新实例
for _, user := range users {
validate := validator.New() // 错误
validate.Struct(user)
}3. 错误处理
go
// ✅ 提供友好的错误信息
if err := validate.Struct(user); err != nil {
// 格式化错误信息
errors := formatValidationErrors(err)
return errors
}📚 扩展阅读
⏭️ 下一章节
CORS 跨域 → 学习跨域处理
💡 提示: Validator 是数据验证的标准库,掌握它可以让数据验证变得简单高效!
