本文介绍: 范围验证: 切片数组map字符串验证长度数值验证大小范围lte:小于等于参数值,validate:“lte=3” (小于等于3)gte:大于等于参数值validate:“lte=120,gte=0” (大于等于0小于等于120)lt:小于参数值validate:“lt=3” (小于3)gt:大于参数值validate:“lt=120,gt=0” (大于0小于120)

背景

一直做的 go 项目中想要方便简洁对接口参数字段进行核验,选择gin 框架适配validator库作为验证组件,基础用法比较简单,对字符数字型校验,对切片数组map 类型范围检验,基础使用起来都比较简单易懂好上手,但近期突然遇到一个意外错误,本来该校验对象数组,却没有按照我预计的核验这个数组里每个对象所属字段的值是否符合要求,由此记录一下。

功能介绍

范围比较验证

范围验证: 切片、数组map字符串,验证其长度数值,验证大小范围

  • lte:小于等于参数值validate:“lte=3” (小于等于3)
  • gte:大于等于参数值validate:“lte=120,gte=0” (大于等于0小于等于120)
  • lt:小于参数值,validate:“lt=3” (小于3)
  • gt:大于参数值,validate:“lt=120,gt=0” (大于0小于120)
  • len:等于参数值,validate:“len=2”,字符串长度必须为n,或者是数组、切片、map的len的值
  • max最大值,小于等于参数值,validate:“max=20” (小于等于20)
  • min最小值,大于等于参数值,validate:“min=2,max=20” (大于等于2小于等于20)
  • ne:不等于,validate:“ne=2” (不等于2)
  • oneof:只能是列举出的值其中一个,这些值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围,validate:“oneof=red green”

标记之间特殊符号说明

字符串验证

特殊字符串验证

例子

简单举例,可自行测试

type UserInfo struct {
	ID   int    `validate:"gt=0"`
	Age  int    `validate:"gt=0"`
	Name string `validate:"required"`
	Sex  string `validate:"required"`
}
func InitUserInfo(id, age int, name, sex string) *UserInfo {
	// new一个校验器
	valid := validator.New()
	// 初始化UserInfo
	userInfo := &UserInfo{
		ID:   id,
		Age:  age,
		Name: name,
		Sex:  sex,
	}
	if err := valid.Struct(userInfo); err != nil {
		fmt.Println("参数校验不通过", err)
	}
	return userInfo
}
func TestValidate(t *testing.T) {
	InitUserInfo(1, 2, "kevin", "男") // 参数校验通过
	InitUserInfo(0, 2, "kevin", "男") // 参数校验不通过 Key: 'UserInfo.ID' Error:Field validation for 'ID' failed on the 'gt' tag
	InitUserInfo(1, 2, "kevin", "")  // 参数校验不通过 Key: 'UserInfo.Sex' Error:Field validation for 'Sex' failed on the 'required' tag
}

扩展问题

我的问题

验证slice

因为项目接口参数的结构体是复杂,往往嵌套对象数组或切片,不是简单由一个结构体就可以概括接收,在项目后续突然发现一个本该检验的对象数组里的某个参数,因对方方也疏忽未传值,导致后面检验出现问题,排查之前虽然问题不在我这边,但的却这个校验字段没有生效,后续排查了一下对于数组或切片或 Map 类型的检验需要使用 dive 才能核验到下一层级的字段里。

举例
sliceone := []string{"123", "onetwothree", "myslicetest", "four", "five"} 
validate.Var(sliceone, "max=15,dive,min=4")
输出
Key: '[0]' Error:Field validation for '[0]' failed on the 'min' tag
Key: '' Error:Field validation for '' failed on the 'min' tag
说明
第二个参数中tag关键字 dive 前面max=15,验证 [] , 也就是验证slice长度,
dive 后面的 min=4,验证slice里的值长度,也就是说 dive 后面的 tag 验证 slice 的值
详细举例

结合上面简单使用的例子使用 dive 核验切片数组对象字段实现


import (
	"fmt"
	"github.com/go-playground/validator/v10"
	"testing"
)

type UserInfo struct {
	ID   int    `validate:"gt=0"`
	Age  int    `validate:"gt=0"`
	Name string `validate:"required"`
	Sex  string `validate:"required"`
}

type Teacher struct {
	Member []*UserInfo `validate:"max=15,dive,required"`
}

func InitUserInfo(id, age int, name, sex string) *UserInfo {
	// new一个校验器
	valid := validator.New()
	// 初始化UserInfo
	userInfo := &UserInfo{
		ID:   id,
		Age:  age,
		Name: name,
		Sex:  sex,
	}
	var menber []*UserInfo
	menber = append(menber, userInfo)
	teacher := &Teacher{
		Member: menber,
	}
	if err := valid.Struct(teacher); err != nil {
		fmt.Println("参数校验不通过", err)
	}
	return userInfo
}

func TestValidate(t *testing.T) {
	InitUserInfo(1, 2, "kevin", "男") // 参数校验通过
	InitUserInfo(0, 2, "kevin", "男") // 参数校验不通过 Key: 'UserInfo.ID' Error:Field validation for 'ID' failed on the 'gt' tag
	InitUserInfo(1, 2, "kevin", "")  // 参数校验不通过 Key: 'UserInfo.Sex' Error:Field validation for 'Sex' failed on the 'required' tag
}

当教师结构体中的参数内包含用户信息结构体,需要核验用户信息的字段时候就需要加上validate:"max=15,dive,required",这样就很核验用户信息结构体字段是否也符合要求
输出如下
在这里插入图片描述
也可不加前面的长度,直接validate:"dive,required"使用

二维slice

当然二维切片也差不多原理

举例:
slicethree := [][]string{} validate.Var(slicethree, "min=2,dive,len=2,dive,required") 
validate.Var(slicethree, "min=2,dive,dive,required")
说明
这里有2个 dive,刚好深入到二维slice,但他们也有不同之处,第二个表达式的第一个dive后没有设置tag。
第一个验证表达式:
min=2:验证第一个 [] 方括号的值长度 ;
len=2:验证第二个 []string 长度;
required:验证slice里的值
第二个验证表达式:
min=2:验证第一个 [] 方括号的值长度 ;
dive: 后没有设置tag值,不验证第二个 []string ;
required: 验证slice里的值

map核验

map的验证中也需要tag关键字 dive, 另外,它还有 keys 和 endkeys 两tag,验证这2个tag之间mapkey,而不是value值。

举例
var mapone map[string]string mapone = map[string]string{"one": "jimmmy", "two": "tom", "three": ""}
 validate := validator.New() 
 err := validate.Var(mapone, "gte=3,dive,keys,eq=1|eq=2,endkeys,required")
输出
Key: '[three]' Error:Field validation for '[three]' failed on the 'eq=1|eq=3' tag
Key: '[three]' Error:Field validation for '[three]' failed on the 'required' tag
Key: '[one]' Error:Field validation for '[one]' failed on the 'eq=1|eq=3' tag
Key: '[two]' Error:Field validation for '[two]' failed on the 'eq=1|eq=3' tag
说明
gte=3:验证map自己的长度;
dive后的 keys,eq=1|eq=2,endkeys:验证map的keys个数,也就是验证 [] 里值。上例中定义了一个string,所以明显报了3个错误。
required:验证 map的值value

嵌套map核验

如:map[[3]string]string,和上面slice差不多,使用多个 dive

举例
var maptwo map[[3]string]string{} validate.Var(maptwo, "gte=3,dive,keys,dive,eq=1|eq=3,endkeys,required")
说明
gte=3: 验证map的长度;
keys,dive,eq=1|eq=3,endkeys:keys和endkeys中有一个dive(深入一级),验证map中key的数组每一个值
required: 验证map的值

参考

golang常用库:字段参数验证库-validator使用
validator代码地址

原文地址:https://blog.csdn.net/ic_xcc/article/details/128387570

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_12654.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注