竹简文档

自定义验证器

7 个预定义自定义验证器详解

自定义验证器

Bamboo Base 提供了 7 个自定义验证器,扩展了 go-playground/validator 的功能。

注册验证器

import (
    "github.com/go-playground/validator/v10"
    xValid "github.com/bamboo-services/bamboo-base-go/validator"
)

validate := validator.New()
if err := xValid.RegisterCustomValidators(validate); err != nil {
    log.Fatal("验证器注册失败:", err)
}

验证器列表

标签说明示例
strict_url严格 URL 验证binding:"strict_url"
strict_uuid严格 UUID 验证binding:"strict_uuid"
alphanum_underscore字母数字下划线binding:"alphanum_underscore"
regexp正则表达式验证binding:"regexp=^[a-z]+$"
enum_int整数枚举验证binding:"enum_int=0 1 2"
enum_string字符串枚举验证binding:"enum_string=a b c"
enum_float浮点数枚举验证binding:"enum_float=0.5 1.0"

strict_url

严格的 URL 格式验证,仅支持 HTTP/HTTPS 协议。

验证规则

^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$

使用示例

type Request struct {
    Website string `binding:"strict_url" label:"网站地址"`
    Avatar  string `binding:"omitempty,strict_url" label:"头像URL"`
}

有效值示例

  • http://example.com
  • https://example.com/path/to/page
  • https://sub.domain.com

无效值示例

  • ftp://example.com(不支持 FTP)
  • example.com(缺少协议)
  • http://localhost(无顶级域名)

strict_uuid

严格的 UUID 格式验证(RFC 4122)。

验证规则

^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

使用示例

type Request struct {
    ID       string `binding:"required,strict_uuid" label:"唯一标识"`
    ParentID string `binding:"omitempty,strict_uuid" label:"父级ID"`
}

有效值示例

  • 123e4567-e89b-12d3-a456-426614174000
  • 550e8400-e29b-41d4-a716-446655440000

alphanum_underscore

验证字符串仅包含字母、数字和下划线。

验证规则

^[a-zA-Z0-9_]+$

使用示例

type Request struct {
    Username string `binding:"required,alphanum_underscore,min=3,max=20" label:"用户名"`
    Code     string `binding:"alphanum_underscore" label:"编码"`
}

有效值示例

  • user_name
  • User123
  • test_user_001

无效值示例

  • user-name(包含连字符)
  • user name(包含空格)
  • 用户名(包含中文)

regexp

使用自定义正则表达式验证字符串。

使用示例

type Request struct {
    // 用户名:6-64位字母数字下划线
    Username string `binding:"regexp=^[a-zA-Z0-9_]{6,64}$" label:"用户名"`

    // 密码:至少包含字母和数字,最少6位
    Password string `binding:"regexp=^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$" label:"密码"`

    // 手机号:中国大陆格式
    Phone string `binding:"regexp=^1[3-9]\\d{9}$" label:"手机号"`
}

注意事项

  • 正则表达式必须是有效的 Go 正则语法
  • 编译失败时验证返回 false
  • 建议在服务端定义正则,避免性能问题

enum_int

验证整数值是否在指定枚举列表中。

支持类型

  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • 基于以上类型的自定义类型

使用示例

type UserGender int8

type Request struct {
    // 性别:0=未知, 1=男, 2=女
    Gender UserGender `binding:"enum_int=0 1 2" label:"性别"`

    // 状态:-1=禁用, 0=待审核, 1=正常
    Status int `binding:"enum_int=-1 0 1" label:"状态"`

    // 优先级:1-5
    Priority uint8 `binding:"enum_int=1 2 3 4 5" label:"优先级"`
}

参数格式

  • 使用空格分隔枚举值
  • 支持负数
  • 必须提供至少一个有效整数

enum_string

验证字符串值是否在指定枚举列表中。

支持类型

  • string
  • 基于 string 的自定义类型

使用示例

type UserRole string

type Request struct {
    // 角色:admin, user, guest
    Role UserRole `binding:"enum_string=admin user guest" label:"角色"`

    // 状态:active, pending, inactive
    Status string `binding:"enum_string=active pending inactive" label:"状态"`

    // 排序方式
    OrderBy string `binding:"enum_string=created_at updated_at name" label:"排序字段"`
}

注意事项

  • 大小写敏感Adminadmin 是不同的值
  • 使用空格分隔枚举值

enum_float

验证浮点数值是否在指定枚举列表中。

支持类型

  • float32, float64
  • 基于以上类型的自定义类型

使用示例

type Rating float64

type Request struct {
    // 评分:0.5 到 5.0,步长 0.5
    Rating Rating `binding:"enum_float=0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0" label:"评分"`

    // 折扣:10%, 20%, 50%
    Discount float32 `binding:"enum_float=0.1 0.2 0.5" label:"折扣"`
}

精度处理

使用 epsilon 容差(1e-9)进行浮点数比较,避免精度问题。


完整示例

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/go-playground/validator/v10"
    xValid "github.com/bamboo-services/bamboo-base-go/validator"
)

type UserGender int8
type UserRole string

type CreateUserRequest struct {
    Username string     `json:"username" binding:"required,alphanum_underscore,min=3,max=20"`
    Password string     `json:"password" binding:"required,regexp=^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$"`
    Email    string     `json:"email" binding:"required,email"`
    Website  string     `json:"website" binding:"omitempty,strict_url"`
    Gender   UserGender `json:"gender" binding:"enum_int=0 1 2"`
    Role     UserRole   `json:"role" binding:"enum_string=admin user guest"`
}

func main() {
    // 注册自定义验证器
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
        xValid.RegisterCustomValidators(v)
    }

    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": err.Error()})
            return
        }
        // 处理请求...
    })
    r.Run()
}

下一步

On this page