golang validators 对 Struct 的字段校验

LLL_小浪 · · 2155 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1、需求:

有时我们需要对接收到的struct字段内容进行验证,比如:

type Student struct {
    Uid   int64
    Name  string
    Age   int64
    Sex   string
    Email string
}
我们需要对结构体内的字段进行验证合法性:
  • Uid的值在某一个范围内
  • Name值的长度在某一个范围内
  • Sex的值符合男或女
  • Email格式正确等等
2、安装:

go get github.com/smokezl/govalidators

3、先来个简单例子,通过golang的structTag来配置验证器:
type Class struct {
    Cid       int64  `validate:"required||integer=10000,_"`
    Cname     string `validate:"required||string=1,5||unique"`
    BeginTime string `validate:"required||datetime=H:i"`
}

type Student struct {
    Uid          int64    `validate:"required||integer=10000,_"`
    Name         string   `validate:"required||string=1,5"`
    Age          int64    `validate:"required||integer=10,30"`
    Sex          string   `validate:"required||in=male,female"`
    Email        string   `validate:"email||user||vm"`
    PersonalPage string   `validate:"url"`
    Hobby        []string `validate:"array=_,2||unique||in=swimming,running,drawing"`
    CreateTime   string   `validate:"datetime"`
    Class        []Class  `validate:"array=1,3"`
}
  • required 判断字段对应的值是否是对应类型的零值
  • integer 表示字段类型是否是整数类型,如果integer后边不接=?,?,那么表示只判断是否是整数类型,如果后边接=?,?,那么有四种写法:
    (1). integer=10 表示字段值 = 10
    (2). integer=_ ,10 表示字段值 <= 10,字段值最小值为字段对应类型的最小值(比如字段对应类型为int8,那么最小为−128),最大值为10
    (3). integer=10, _ 表示字段值 >= 10,字段值最小值为10,最大值为字段对应类型的最大值(比如字段对应类型为int8,那么最大为127)
    (4). integer=1,20 表示字段值 >=1 并且 <= 20
  • array、string 同 integer,array=?,? 表示元素个数范围,string=?,? 表示字符串长度范围
  • email 表示字段值是否是合法的email地址
  • url 表示字段值是否是合法的url地址
  • in 表示字段值在in指定的值中,比如 Hobby 字段中,in=swimming,running,drawing,表示 Hobby 字段的值,只能是swimming,running,drawing中的一个或多个
  • datetime 表示字段值符合日期类型,如果datetime后边不接=?,那么默认为Y-m-d H:i:s,否则验证器会按照指定格式判断,比如 datetime=Y-m、datetime=Y/m/d H:i:s等,可以是Y m d H i s 的随意拼接
  • unique 表示字段值唯一,比如 Hobby 字段的 unique,表示 Hobby 字段值唯一,Class 中,Cname 字段的 unique,表示 Cname 字段值唯一。
package main

import (
    "fmt"
    "github.com/smokezl/govalidators"
)

//把上面的两个Struct复制到此处

func goValidators() {
    validator := govalidators.New()
    student := &Student{
        Uid:          1234567,
        Name:         "张三1111",
        Age:          31,
        Sex:          "male1",
        Email:        "@qq.com",
        PersonalPage: "www.abcd.com",
        Hobby:        []string{"swimming", "singing"},
        CreateTime:   "2018-03-03 05:60:00",
        Class: []Class{
            Class{
                Cid:       12345678,
                Cname:     "语文",
                BeginTime: "13:00",
            },
            Class{
                Cid:       22345678,
                Cname:     "数学",
                BeginTime: "13:00",
            },
            Class{
                Cid:       32345678,
                Cname:     "数学",
                BeginTime: "13:60",
            },
        },
    }
    errList := validator.Validate(student)
    if errList != nil {
        for _, err := range errList {
            fmt.Println("err:", err)
        }
    }
    
}

func main() {
    goValidators()
}

执行结果:

err: Name should be betwween 1 and 5 chars long
err: Age should be betwween 10 and 30
err: Sex is not in params [male female]
err: Email is not a email address
err: validator user not exist
err: validator vm not exist
err: PersonalPage is not a url
err: Hobby is not in params [swimming running drawing]
err: CreateTime is not a date time
err: Cname is not unique
err: BeginTime is not a date time

有时,我们不需要将错误全部收集到,而是只要其中一个有错,可以用 LazyValidate 方法:

err := validator.LazyValidate(student)
if err != nil {
    fmt.Println("err:", err)
}

执行结果:

err: Name should be betwween 1 and 5 chars long

如果我们想把刚才的报错信息,都改为中文,那么就可以对每个验证器错误 msg 进行自定义:

//自定义msg错误信息
    validator := govalidators.New()
    validator.SetValidators(map[string]interface{}{
        "string": &govalidators.StringValidator{
            Range: govalidators.Range{
                RangeEMsg: map[string]string{
                    "between": "[name] 长度必须在 [min] 和 [max] 之间",
                },
            },
        },
        "integer": &govalidators.IntegerValidator{
            Range: govalidators.Range{
                RangeEMsg: map[string]string{
                    "between": "[name] 的值必须在 [min] 和 [max] 之间",
                },
            },
        },
        "in": &govalidators.InValidator{
            EMsg: "[name] 的值必须为 [args] 中的一个",
        },
        "email": &govalidators.EmailValidator{
            EMsg: "[name] 不是一个有效的email地址",
        },
        "url": &govalidators.UrlValidator{
            EMsg: "[name] 不是一个有效的url地址",
        },
        "datetime": &govalidators.DateTimeValidator{
            EMsg: "[name] 不是一个有效的日期",
        },
        "unique": &govalidators.UniqueValidator{
            EMsg: "[name] 不是唯一的",
        },
    })
    errList := validator.Validate(student)
    if errList != nil {
        for _, err := range errList {
            fmt.Println("err:", err)
        }
    }

执行结果:

err: Name 长度必须在 1 和 5 之间
err: Age 的值必须在 10 和 30 之间
err: Sex 的值必须为 [male female] 中的一个
err: Email 不是一个有效的email地址
err: validator user not exist
err: validator vm not exist
err: PersonalPage 不是一个有效的url地址
err: Hobby 的值必须为 [swimming running drawing] 中的一个
err: CreateTime 不是一个有效的日期
err: Cname 不是唯一的
err: BeginTime 不是一个有效的日期

在校验Struct时是根据下面链接中的文章做的,其中还有一些扩展目前还没有测。
更多详情点击:https://www.jianshu.com/p/64757be312a4


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:LLL_小浪

查看原文:golang validators 对 Struct 的字段校验

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2155 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传