问题
开发服务接口,需要对提交过来的数据进行校验,检查合法性。
如果提交的参数一两个,可以一个个检查判断、要是提交的数据比较多,那么这就比较繁琐了。
在 Go 语言中,使用比较多的是 validator 包,
通过反射 struct 结构 tag,获取数据进行验证。
实践
安装
go get github.com/go-playground/validator/v10
栗子:
type Order struct {
OrderId string `json:"orderId" validate:"required"`
Code string `json:"code" validate:"required,len=6"`
}
- validator 包定义了一些常用的规则
- backed_in.go
Gin 中使用
gin 框架已经支持 validator
比如注册信息
type RegisterInfo struct {
UserName string `form:"userName" json:"userName" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
RePassword string `form:"rePassword" json:"rePassword" binding:"required,eqfield=Password"`
Phone string `form:"phone" json:"phone" binding:"required"`
SmsCode string `form:"smsCode" json:"smsCode" binding:"required"`
Email string `form:"email" json:"email" binding:"omitempty,email"`
}
- 使用 binding tag 作为修饰
自定义校验器
栗子:实现一个登录接口,登录方式有密码和短信两种方式,使用 validator 进行校验。
type LoginInfo struct {
UserName string `json:"userName"`
Password string `json:"password"`
Mobile string `json:"mobile"`
SmsCode string `json:"smsCode"`
LoginType string `json:"loginType" binding:"required,valuein=password sms"`
}
- valuein 为一个自定义的校验器
package validator
import (
"sort"
"strings"
"github.com/go-playground/validator/v10"
)
func in(target string, arr []string) bool {
sort.Strings(arr)
index := sort.SearchStrings(arr, target)
if index < len(arr) && arr[index] == target {
return true
}
return false
}
func ValueIn(fl validator.FieldLevel) bool {
param := fl.Param()
if param == "" {
return true
}
field := fl.Field()
values := strings.Split(param, " ")
// log.Println(field.Interface())
// log.Println(field.Kind(), currentField.Kind())
// log.Printf("currentKind %v nullable %v found %v", currentKind, nullable, found)
return in(field.String(), values)
}
- valuein=password sms,在注册校验器,接收 validator.FieldLevel 参数,可以从 validator.FieldLevel 接口获取绑定的参数
- 获取绑定的参数可以进一步做校验
- 获取到参数,转换为切片,判断是否存在切片中
- func ValueIn(fl validator.FieldLevel) bool {} 返回一个 bool 值,true 表示校验通过,false 表示校验失败
注册校验器
// 绑定验证器
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("valuein", mv.ValueIn)
}
验证
访问登录接口 http://localhost:8090/api/v1/account/login
参数
{
"userName": "tom",
"password": "123456",
"loginType": ""
}
不传或者把loginType参数传错
{
"code": 10002,
"errMsg": "Key: 'LoginInfo.LoginType' Error:Field validation for 'LoginType' failed on the 'valuein' tag",
"message": "参数有误"
}
参数 loginType sms\password
{
"userName": "tom",
"password": "123456",
"loginType": "sms"
}
返回
{
"code": 200,
"data": 1,
"message": "请求成功"
}