Golang 验证 struct 字段的数据格式
来源:互联网 发布:风险矩阵法的作用 编辑:程序博客网 时间:2024/06/03 21:45
假设我们有如下结构体:
type User struct { Id int Name string Bio string Email string }
我们需要对结构体内的字段进行验证合法性:
Id的值在某一个范围内。
Name的长度在某一个范围内。
Email格式正确。
我们可能会这么写:
user := User{ Id: 0, Name: "superlongstring", Bio: "", Email: "foobar",}if user.Id < 1 && user.Id > 1000 { return false}if len(user.Name) < 2 && len(user.Name) > 10 { return false}if !validateEmail(user.Email) { return false}
这样的话代码比较冗余,而且如果结构体新加字段,还需要再修改验证函数再加一段if判断。这样代码比较冗余。我们可以借助golang的structTag来解决上述的问题:
type User struct { Id int `validate:"number,min=1,max=1000"` Name string `validate:"string,min=2,max=10"` Bio string `validate:"string"` Email string `validate:"email"`}validate:"number,min=1,max=1000"就是structTag。
以下是具体实现:
package mainimport ( "fmt" "reflect" "regexp" "strings")const tagName = "validate"// 邮箱验证正则var mailRe = regexp.MustCompile(`\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z`)// Validator 验证接口type Validator interface { Validate(interface{}) (bool, error)}type DefaultValidator struct{}func (v DefaultValidator) Validate(val interface{}) (bool, error) { return true, nil}type StringValidator struct { Min int Max int}func (v StringValidator) Validate(val interface{}) (bool, error) { l := len(val.(string)) if l == 0 { return false, fmt.Errorf("cannot be blank") } if l < v.Min { return false, fmt.Errorf("should be at least %v chars long", v.Min) } if v.Max >= v.Min && l > v.Max { return false, fmt.Errorf("should be less than %v chars long", v.Max) } return true, nil}type NumberValidator struct { Min int Max int}func (v NumberValidator) Validate(val interface{}) (bool, error) { num := val.(int) if num < v.Min { return false, fmt.Errorf("should be greater than %v", v.Min) } if v.Max >= v.Min && num > v.Max { return false, fmt.Errorf("should be less than %v", v.Max) } return true, nil}type EmailValidator struct{}func (v EmailValidator) Validate(val interface{}) (bool, error) { if !mailRe.MatchString(val.(string)) { return false, fmt.Errorf("is not a valid email address") } return true, nil}func getValidatorFromTag(tag string) Validator { args := strings.Split(tag, ",") switch args[0] { case "number": validator := NumberValidator{} //将structTag中的min和max解析到结构体中 fmt.Sscanf(strings.Join(args[1:], ","), "min=%d,max=%d", &validator.Min, &validator.Max) return validator case "string": validator := StringValidator{} fmt.Sscanf(strings.Join(args[1:], ","), "min=%d,max=%d", &validator.Min, &validator.Max) return validator case "email": return EmailValidator{} } return DefaultValidator{}}func validateStruct(s interface{}) []error { errs := []error{} v := reflect.ValueOf(s) for i := 0; i < v.NumField(); i++ { // 利用反射获取structTag tag := v.Type().Field(i).Tag.Get(tagName) if tag == "" || tag == "-" { continue } validator := getValidatorFromTag(tag) valid, err := validator.Validate(v.Field(i).Interface()) if !valid && err != nil { errs = append(errs, fmt.Errorf("%s %s", v.Type().Field(i).Name, err.Error())) } } return errs}// User user structtype User struct { ID int `validate:"number,min=1,max=1000"` Name string `validate:"string,min=2,max=10"` Bio string `validate:"string"` Email string `validate:"email"`}func main() { user := User{ ID: 0, Name: "superlongstring", Bio: "", Email: "foobar", } fmt.Println("Errors:") for i, err := range validateStruct(user) { fmt.Printf("\t%d. %s\n", i+1, err.Error()) }}
当然也可以直接使用一些第三方的库来实现,推荐
gopkg.in/go-playground/validator.v9
/github.com/asaskevich/govalidator
阅读全文
0 0
- Golang 验证 struct 字段的数据格式
- golang遍历结构体(struct)字段对应的值,切片(slice),字典(map)
- golang的参数验证
- golang struct
- 常用的js数据格式验证
- golang语言中struct的初始化方式
- golang入门--struct Tag的语法
- typedef struct和struct的用法验证
- golang 验证表单的输入
- Golang 父子对象与JSON互相转换以及struct结构体内部的反引号该如何定义字段编码生成json字符串的写法
- golang struct 面向对象
- golang struct to map
- golang struct继承测试
- play的字段验证
- 利用reflect设置struct的字段
- golang 内置函数new() 和struct{} 初始化的区别
- golang xml marshal对应的struct两种表示方法
- golang 获取一个结构体 struct 大小的代码
- Hadoop集群活跃节点为0解决方案
- SimSo Web 开发者手册(中文版)
- ES简要知识点
- 首届全球程序员节:一个群体、一张名片、一方生态
- 分布式开发简介
- Golang 验证 struct 字段的数据格式
- Android获取应用列表
- log4j的分类打印
- 数据结构
- HashMap的遍历
- 【第二届蓝桥杯】中奖计算
- 二进制快速排序
- 选取表单和表单元素
- jQuery相关API及知识点