Validator 验证器包
这是一个功能完整的验证器包,提供了HTTP请求验证和业务逻辑验证的完整解决方案。
📁 包结构
internal/shared/validator/
├── validator.go           # HTTP请求验证器主逻辑
├── custom_validators.go   # 自定义验证器实现
├── translations.go        # 中文翻译
├── business.go           # 业务逻辑验证接口
└── README.md            # 使用说明
🚀 特性
1. HTTP请求验证
- 自动绑定和验证请求体、查询参数、路径参数
- 中文错误消息
- 集成到Gin框架
- 统一的错误响应格式
2. 业务逻辑验证
- 独立的业务验证器
- 可在任何地方调用的验证方法
- 丰富的预定义验证规则
3. 自定义验证规则
- 手机号验证 (phone)
- 强密码验证 (strong_password)
- 用户名验证 (username)
- 统一社会信用代码验证 (social_credit_code)
- 身份证号验证 (id_card)
- UUID验证 (uuid)
- URL验证 (url)
- 产品代码验证 (product_code)
- 价格验证 (price)
- 排序方向验证 (sort_order)
📖 使用方法
1. HTTP请求验证
在Handler中使用:
type UserHandler struct {
    validator interfaces.RequestValidator
    // ... 其他依赖
}
func (h *UserHandler) Register(c *gin.Context) {
    var cmd commands.RegisterUserCommand
    
    // 自动绑定和验证请求体
    if err := h.validator.BindAndValidate(c, &cmd); err != nil {
        return // 验证失败会自动返回错误响应
    }
    
    // 验证查询参数
    var query queries.UserListQuery
    if err := h.validator.ValidateQuery(c, &query); err != nil {
        return
    }
    
    // 验证路径参数
    var param queries.UserIDParam
    if err := h.validator.ValidateParam(c, ¶m); err != nil {
        return
    }
    
    // 继续业务逻辑...
}
2. DTO定义
在DTO中使用验证标签:
type RegisterUserCommand struct {
    Phone           string `json:"phone" binding:"required,phone"`
    Password        string `json:"password" binding:"required,strong_password"`
    ConfirmPassword string `json:"confirm_password" binding:"required,eqfield=Password"`
    Email           string `json:"email" binding:"omitempty,email"`
    Username        string `json:"username" binding:"required,username"`
}
type EnterpriseInfoCommand struct {
    CompanyName       string `json:"company_name" binding:"required,min=2,max=100"`
    UnifiedSocialCode string `json:"unified_social_code" binding:"required,social_credit_code"`
    LegalPersonName   string `json:"legal_person_name" binding:"required,min=2,max=20"`
    LegalPersonID     string `json:"legal_person_id" binding:"required,id_card"`
    LegalPersonPhone  string `json:"legal_person_phone" binding:"required,phone"`
}
type ProductCommand struct {
    Name       string  `json:"name" binding:"required,min=2,max=100"`
    Code       string  `json:"code" binding:"required,product_code"`
    Price      float64 `json:"price" binding:"price,min=0"`
    CategoryID string  `json:"category_id" binding:"required,uuid"`
    WebsiteURL string  `json:"website_url" binding:"omitempty,url"`
}
3. 业务逻辑验证
在Service中使用:
import "tyapi-server/internal/shared/validator"
type UserService struct {
    businessValidator *validator.BusinessValidator
}
func NewUserService() *UserService {
    return &UserService{
        businessValidator: validator.NewBusinessValidator(),
    }
}
func (s *UserService) ValidateUserData(phone, password string) error {
    // 验证手机号
    if err := s.businessValidator.ValidatePhone(phone); err != nil {
        return fmt.Errorf("手机号验证失败: %w", err)
    }
    
    // 验证密码强度
    if err := s.businessValidator.ValidatePassword(password); err != nil {
        return fmt.Errorf("密码验证失败: %w", err)
    }
    
    // 验证结构体
    userData := UserData{Phone: phone, Password: password}
    if err := s.businessValidator.ValidateStruct(userData); err != nil {
        return fmt.Errorf("用户数据验证失败: %w", err)
    }
    
    return nil
}
func (s *UserService) ValidateEnterpriseInfo(code, idCard string) error {
    // 验证统一社会信用代码
    if err := s.businessValidator.ValidateSocialCreditCode(code); err != nil {
        return err
    }
    
    // 验证身份证号
    if err := s.businessValidator.ValidateIDCard(idCard); err != nil {
        return err
    }
    
    return nil
}
🔧 可用的验证规则
标准验证规则
- required- 必填
- omitempty- 可为空
- min=n- 最小长度/值
- max=n- 最大长度/值
- len=n- 固定长度
- email- 邮箱格式
- oneof=a b c- 枚举值
- eqfield=Field- 字段相等
- gt=n- 大于某值
自定义验证规则
- phone- 中国手机号 (1[3-9]xxxxxxxxx)
- strong_password- 强密码 (8位以上,包含大小写字母和数字)
- username- 用户名 (字母开头,3-20位字母数字下划线)
- social_credit_code- 统一社会信用代码 (18位)
- id_card- 身份证号 (18位)
- uuid- UUID格式
- url- URL格式
- product_code- 产品代码 (3-50位字母数字下划线连字符)
- price- 价格 (非负数)
- sort_order- 排序方向 (asc/desc)
🌐 错误消息
所有错误消息都已本地化为中文:
{
  "code": 422,
  "message": "请求参数验证失败",
  "data": null,
  "errors": {
    "phone": ["手机号必须是有效的手机号"],
    "password": ["密码强度不足,必须包含大小写字母和数字,且不少于8位"],
    "confirm_password": ["确认密码必须与密码一致"]
  }
}
🔄 依赖注入
在 container.go 中已配置:
fx.Provide(
    validator.NewRequestValidator,  // HTTP请求验证器
),
业务验证器可以在需要时创建:
bv := validator.NewBusinessValidator()
📝 最佳实践
- DTO验证: 在DTO中使用binding标签进行声明式验证
- 业务验证: 在业务逻辑中使用BusinessValidator进行程序化验证
- 错误处理: 验证错误会自动返回统一格式的HTTP响应
- 性能: 验证器实例可以复用,建议在依赖注入中管理
🧪 测试示例
参考 examples/validator_usage.go 文件中的完整使用示例。
这个验证器包提供了完整的验证解决方案,既可以用于HTTP请求的自动验证,也可以在业务逻辑中进行程序化验证,确保数据的完整性和正确性。