Gin 接口开发、Validator 参数校验器 | Go 主题月

2,371 阅读2分钟

问题

开发服务接口,需要对提交过来的数据进行校验,检查合法性。

如果提交的参数一两个,可以一个个检查判断、要是提交的数据比较多,那么这就比较繁琐了。

在 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

image-20210401210727929

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": "请求成功"
}