抛出问题:
使用默认的数据校验,校验失败时,返回的提示信息为英文,且根据提示信息没法判断校验失败的原因,体验感很差。
解决:
自定义校验,注册翻译器
涉及的包:
en2 "github.com/go-playground/locales/en"
zh2 "github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
en_translations "github.com/go-playground/validator/v10/translations/en"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
结构体在校验时不在使用binding,使用validate。
var query struct {
Name string `form:"name" json:"name,omitempty" validate:"omitempty,max=128"`
Id int `form:"id" json:"id,omitempty" validate:"omitempty,numeric,gte=1"`
PerShopId string `form:"per_shop_id" json:"per_shop_id,omitempty"`
PerCategory string `form:"per_category" json:"per_category,omitempty"`
PerErpArea string `form:"per_erp_area" json:"per_erp_area,omitempty"`
Page int `form:"page" json:"page" validate:"required,gte=1"`
PageSize int `form:"page_size" json:"page_size" validate:"required,gte=1"`
}
构建语言转换器及注册:
import (
"fmt"
"github.com/gin-gonic/gin"
lzh "github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
translations "github.com/go-playground/validator/v10/translations/zh"
"strings"
"sync"
"sync/atomic"
)
var (
uni *ut.UniversalTranslator
validate *validator.Validate
validateOnce = &ErrorOnce{}
trans ut.Translator
)
type ErrorOnce struct {
m sync.Mutex
done uint32
}
func (v *ErrorOnce) Do(f func() error) error {
if atomic.LoadUint32(&v.done) == 1 {
return nil
}
return v.doSlow(f)
}
func (v *ErrorOnce) doSlow(f func() error) error {
v.m.Lock()
defer v.m.Unlock()
var err error
if v.done == 0 {
err = f()
if err == nil {
atomic.StoreUint32(&v.done, 1)
}
}
return err
}
func GetValidate() *validator.Validate {
err := validateOnce.Do(func() error {
zh := lzh.New()
uni = ut.New(zh)
validate = validator.New()
trans, _ = uni.GetTranslator("zh")
return translations.RegisterDefaultTranslations(validate, trans)
})
fmt.Println("GetValidate-err->", err)
return validate
}
func GetErrInfo(err error) (map[string]string, []string) {
errs := err.(validator.ValidationErrors)
sliceErrs := make([]string, len(errs))
for i, e := range errs {
sliceErrs[i] = e.Translate(trans)
}
return errs.Translate(trans), sliceErrs
}
使用:
err := c.ShouldBindQuery(&query)
if err != nil {
c.JSON(http.StatusBadRequest, info)
return
}
//参数校验
if err = GetValidate().Struct(query); err != nil {
info, _ := GetErrInfo(err)
c.JSON(http.StatusBadRequest, info)
return
}