在写项目的时候我们经常会遇到参数校验的问题,比如用户输入合理的email、url,或者限制用户的密码长度等等内容,在之前我自己写项目的时候,总是使用正则表达式来进行验证,但由于正则表达式相对难懂并且使用起来不方便,这里介绍其余两种参数校验的方式。
govalidator
先看一下官网的介绍:A package of validators and sanitizers for strings, structs and collections. Based on validator.js.
使用:
go get github.com/asaskevich/govalidator
然后他有一个选项需要我们去配置
func init() {
govalidator.SetFieldsRequiredByDefault(true)
}
在上面就是如果SetFieldsRequiredByDefault设置为true,那么我们进行校验的所有结构题如果没有声明valid:“-” 或 valid:(“email,optional”)时都会校验失败(也就是什么都没有的会失败,它相当于给每个结构体内所有字段添加了valid:"required"标签),所以我们一般会把这个选项设置为false,这样它就只会校验我们在结构题中设置需要校验的变量。
上面的valid:(“email,optional”)意思是这个值可以是指针,也就是如果为nil,会通过验证。看一下代码大家就理解了
// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
type exampleStruct struct {
Name string ``
Email string `valid:"email"`
}
// this, however, will only fail when Email is empty or an invalid email address:
type exampleStruct2 struct {
Name string `valid:"-"`
Email string `valid:"email"`
}
// lastly, this will only fail when Email is an invalid email address but not when it's empty:
type exampleStruct2 struct {
Name string `valid:"-"`
Email string `valid:"email,optional"`
}
然后官网有它的函数列表,感兴趣的可以去看govalidator官网
下面我们来看几个使用
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
println(govalidator.IsType("Bob", "string"))
println(govalidator.IsType(1, "int"))
i := 1
println(govalidator.IsType(&i, "*int"))
type User struct {
Name string `valid:"type(string)"`
Age int `valid:"type(int)"`
Meta interface{} `valid:"type(string)"`
}
result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
if err != nil {
println("error: " + err.Error())
}
println(result)
根据这些例子,大家应该也可以理解怎么使用它来作为验证了,我看官网上还可以自己定义验证逻辑等,但因为我只是用它来做格式的认证,所以各位可以自行到官网查看
使用protovalidate
protovalidate是一种定义在proto中的一种验证方式,我们使用protobuf语法定义我们需啊的参数验证,这里来看一下语法
数字类型
// 参数必须大于 0
int64 id = 1 [(validate.rules).int64 = {gt: 0}];
// 参数必须在 0 到 120 之间
int32 age = 2 [(validate.rules).int32 = {gt:0, lte: 120}];
// 参数是 1 或 2 或 3
uint32 code = 3 [(validate.rules).uint32 = {in: [1,2,3]}];
// 参数不能是 0 或 99.99
float score = 1 [(validate.rules).float = {not_in: [0, 99.99]}];
bool类型
// 参数必须为 true
bool state = 5 [(validate.rules).bool.const = true];
// 参数必须为 false
bool state = 5 [(validate.rules).bool.const = false];
文本类型
// 参数必须为 /hello
string path = 6 [(validate.rules).string.const = "/hello"];
// 参数文本长度必须为 11
string phone = 7 [(validate.rules).string.len = 11];
// 参数文本长度不能小于 10 个字符
string explain = 8 [(validate.rules).string.min_len = 10];
// 参数文本长度不能小于 1 个字符并且不能大于 10 个字符
string name = 9 [(validate.rules).string = {min_len: 1, max_len: 10}];
// 参数文本使用正则匹配,匹配必须是非空的不区分大小写的十六进制字符串
string card = 10 [(validate.rules).string.pattern = "(?i)^[0-9a-f]+$"];
// 参数文本必须是 email 格式
string email = 11 [(validate.rules).string.email = true];
使用的时候就是
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--validate_out=paths=source_relative,lang=go:. \
xxxx.proto
if err := protovalidate.Validate(req); err != nil {
return nil, pkg.ErrorValidateConvertKratos(err)
}
Comments NOTHING