diff --git a/validator/govalidator/README.md b/validator/govalidator/README.md new file mode 100644 index 0000000..616e00b --- /dev/null +++ b/validator/govalidator/README.md @@ -0,0 +1,34 @@ +### Quick Start + +## Prerequesites: + +- Install `go-zero`: + +```shell +go get -u github.com/zeromicro/go-zero +``` + + + ++ Download the module: + +```shell +go get -u github.com/zeromicro/zero-contrib/validator/govalidator +``` + +## For example: + +```go +func (l *RegisterLogic) Register(in *user.RegisterReq) (*user.CommonReply, error) { + // todo: add your logic here and delete this line + .... + err := govalidator.DefaultGetValidParams(l.ctx, in) + if err != nil { + return nil, errorx.NewDefaultError(fmt.Sprintf("validate校验错误: %v", err)) + } + ..... + +} + +``` + diff --git a/validator/govalidator/go.mod b/validator/govalidator/go.mod new file mode 100644 index 0000000..5dedb65 --- /dev/null +++ b/validator/govalidator/go.mod @@ -0,0 +1,16 @@ +module govalidator + +go 1.20 + +require ( + github.com/go-playground/locales v0.14.1 + github.com/go-playground/universal-translator v0.18.1 + github.com/go-playground/validator/v10 v10.13.0 +) + +require ( + github.com/leodido/go-urn v1.2.3 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect +) diff --git a/validator/govalidator/go.sum b/validator/govalidator/go.sum new file mode 100644 index 0000000..c137fcf --- /dev/null +++ b/validator/govalidator/go.sum @@ -0,0 +1,31 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ= +github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= +github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= +github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/validator/govalidator/validator.go b/validator/govalidator/validator.go new file mode 100644 index 0000000..08719bd --- /dev/null +++ b/validator/govalidator/validator.go @@ -0,0 +1,115 @@ +package govalidator + +import ( + "context" + "errors" + "github.com/go-playground/locales/en" + "github.com/go-playground/locales/zh" + ut "github.com/go-playground/universal-translator" + "github.com/go-playground/validator/v10" + enTranslations "github.com/go-playground/validator/v10/translations/en" + zhTranslations "github.com/go-playground/validator/v10/translations/zh" + "reflect" + "regexp" + "strings" +) + +const ( + ValidatorKey = "ValidatorKey" + TranslatorKey = "TranslatorKey" + locale = "chinese" +) + +func TransInit(ctx context.Context) context.Context { + // Set the supported language + chinese := zh.New() + english := en.New() + // Set up an internationalized translator + uni := ut.New(chinese, chinese, english) + // Set up validators + val := validator.New() + // Take the translator instance as an argument + trans, _ := uni.GetTranslator(locale) + // Register the translator with validatorfw + switch locale { + case "chinese": + zhTranslations.RegisterDefaultTranslations(val, trans) + // Register a custom method to get a tag with fld.Tag.Get("comment") + val.RegisterTagNameFunc(func(fld reflect.StructField) string { + return fld.Tag.Get("comment") + }) + val.RegisterValidation("phone", func(fl validator.FieldLevel) bool { + phone := fl.Field().String() + // Validate phone number with a regular expression + pattern := `^1[3456789]\d{9}$` + matched, _ := regexp.MatchString(pattern, phone) + return matched + }) + zhTranslations.RegisterDefaultTranslations(val, trans) + val.RegisterTranslation("phone", trans, func(ut ut.Translator) error { + return ut.Add("phone", "{0}格式不正确,必须为手机号码", true) + }, func(ut ut.Translator, fe validator.FieldError) string { + t, _ := ut.T("phone", fe.Field()) + return t + }) + + case "english": + enTranslations.RegisterDefaultTranslations(val, trans) + val.RegisterTagNameFunc(func(fld reflect.StructField) string { + return fld.Tag.Get("en_comment") + }) + val.RegisterValidation("phone", func(fl validator.FieldLevel) bool { + phone := fl.Field().String() + // Validate phone number with a regular expression + pattern := `^1[3456789]\d{9}$` + matched, _ := regexp.MatchString(pattern, phone) + return matched + }) + zhTranslations.RegisterDefaultTranslations(val, trans) + val.RegisterTranslation("phone", trans, func(ut ut.Translator) error { + return ut.Add("phone", "The {0} format is incorrect;it must be a cell phone number", true) + }, func(ut ut.Translator, fe validator.FieldError) string { + t, _ := ut.T("phone", fe.Field()) + return t + }) + } + + ctx = context.WithValue(ctx, ValidatorKey, val) + ctx = context.WithValue(ctx, TranslatorKey, trans) + return ctx +} + +func DefaultGetValidParams(ctx context.Context, params interface{}) error { + ctx = TransInit(ctx) + err := validate(ctx, params) + if err != nil { + return err + } + return nil +} + +func validate(ctx context.Context, params interface{}) error { + // Get the validatorfw + val, ok := ctx.Value(ValidatorKey).(*validator.Validate) + if !ok { + return errors.New("Validator not found in context") + } + + // Get the translator + tran, ok := ctx.Value(TranslatorKey).(ut.Translator) + if !ok { + return errors.New("Translator not found in context") + } + err := val.Struct(params) + // If the data validation fails, output all err in a slice + if err != nil { + errs := err.(validator.ValidationErrors) + sliceErrs := []string{} + for _, e := range errs { + // use the validatorfw. ValidationErrors types in the `Translate` method for translation + sliceErrs = append(sliceErrs, e.Translate(tran)) + } + return errors.New(strings.Join(sliceErrs, ",")) + } + return nil +} diff --git a/validator/govalidator/validtor_test.go b/validator/govalidator/validtor_test.go new file mode 100644 index 0000000..b5c9eb0 --- /dev/null +++ b/validator/govalidator/validtor_test.go @@ -0,0 +1,29 @@ +package govalidator + +import ( + "context" + "fmt" + "testing" +) + +type User struct { + UserId int64 + PassWord string `validate:"min=6,max=20"` + UserNick string `validate:"min=4,max=15"` + UserPhone string `validate:"phone"` + UserEmail string `validate:"email"` +} + +func TestValid(t *testing.T) { + user := User{ + UserId: 1, + PassWord: "123", + UserNick: "fjwenfjwkfnkwnefjwnfwjkf", + UserPhone: "12g2f", + UserEmail: "lijfwf", + } + err := DefaultGetValidParams(context.Background(), user) + if err != nil { + fmt.Println(err) // PassWord长度必须至少为6个字符,UserNick长度不能超过15个字符,UserPhone格式不正确,必须为手机号码,UserEmail必须是一个有效的邮箱 + } +}