From c8c28770fb2ce6f805e1ff1beb9826bbdc5cee41 Mon Sep 17 00:00:00 2001 From: John Guo Date: Tue, 18 May 2021 20:51:31 +0800 Subject: [PATCH] change Error from struct to interface for package gvalid;error string update for package gdb --- .example/i18n/gi18n/gi18n-dir.go | 5 +- .example/i18n/gi18n/gi18n-file.go | 5 +- .example/i18n/gi18n/gi18n.go | 12 +++- .example/i18n/gi18n/http_view_i18n.go | 12 ++-- .../net/ghttp/client/middleware/client.go | 64 +++++++++++++++++++ .../net/ghttp/client/middleware/server.go | 17 +++++ .../ghttp/server/request/json-xml/test2.go | 2 +- .../server/request/validation/validation2.go | 2 +- database/gdb/gdb.go | 12 +++- frame/gins/gins_database.go | 4 +- i18n/gi18n/gi18n.go | 1 - i18n/gi18n/gi18n_manager.go | 1 - util/gvalid/gvalid.go | 8 +-- util/gvalid/gvalid_error.go | 49 ++++++++------ util/gvalid/gvalid_validator_check.go | 6 +- util/gvalid/gvalid_validator_check_map.go | 4 +- util/gvalid/gvalid_validator_check_struct.go | 22 ++++--- util/gvalid/gvalid_z_example_test.go | 2 + util/gvalid/gvalid_z_unit_custom_rule_test.go | 8 +-- util/gvalid/gvalid_z_unit_i18n_test.go | 2 +- 20 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 .example/net/ghttp/client/middleware/client.go create mode 100644 .example/net/ghttp/client/middleware/server.go diff --git a/.example/i18n/gi18n/gi18n-dir.go b/.example/i18n/gi18n/gi18n-dir.go index e9359c5ea..552298176 100644 --- a/.example/i18n/gi18n/gi18n-dir.go +++ b/.example/i18n/gi18n/gi18n-dir.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "github.com/gogf/gf/i18n/gi18n" @@ -13,6 +14,6 @@ func main() { if err != nil { panic(err) } - fmt.Println(t.Translate(`hello`)) - fmt.Println(t.Translate(`{#hello}{#world}!`)) + fmt.Println(t.Translate(context.TODO(), `hello`)) + fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`)) } diff --git a/.example/i18n/gi18n/gi18n-file.go b/.example/i18n/gi18n/gi18n-file.go index 1a6d337c3..f1a4423ee 100644 --- a/.example/i18n/gi18n/gi18n-file.go +++ b/.example/i18n/gi18n/gi18n-file.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "github.com/gogf/gf/i18n/gi18n" @@ -13,6 +14,6 @@ func main() { if err != nil { panic(err) } - fmt.Println(t.Translate(`hello`)) - fmt.Println(t.Translate(`{#hello}{#world}!`)) + fmt.Println(t.Translate(context.TODO(), `hello`)) + fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`)) } diff --git a/.example/i18n/gi18n/gi18n.go b/.example/i18n/gi18n/gi18n.go index 630d5a954..17d830c0d 100644 --- a/.example/i18n/gi18n/gi18n.go +++ b/.example/i18n/gi18n/gi18n.go @@ -1,8 +1,10 @@ package main import ( + "context" "fmt" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/i18n/gi18n" ) func main() { @@ -10,6 +12,12 @@ func main() { orderId = 865271654 orderAmount = 99.8 ) - fmt.Println(g.I18n().Tfl(`en`, `{#OrderPaid}`, orderId, orderAmount)) - fmt.Println(g.I18n().Tfl(`zh-CN`, `{#OrderPaid}`, orderId, orderAmount)) + fmt.Println(g.I18n().Tf( + gi18n.WithLanguage(context.TODO(), `en`), + `{#OrderPaid}`, orderId, orderAmount, + )) + fmt.Println(g.I18n().Tf( + gi18n.WithLanguage(context.TODO(), `zh-CN`), + `{#OrderPaid}`, orderId, orderAmount, + )) } diff --git a/.example/i18n/gi18n/http_view_i18n.go b/.example/i18n/gi18n/http_view_i18n.go index ca5956c7b..1f1cc2302 100644 --- a/.example/i18n/gi18n/http_view_i18n.go +++ b/.example/i18n/gi18n/http_view_i18n.go @@ -2,15 +2,19 @@ package main import ( "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/i18n/gi18n" "github.com/gogf/gf/net/ghttp" ) func main() { - g.I18n().SetPath("/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/i18n/gi18n/i18n") s := g.Server() - s.BindHandler("/", func(r *ghttp.Request) { - r.Response.WriteTplContent(`{#hello}{#world}!`, g.Map{ - "I18nLanguage": r.Get("lang", "zh-CN"), + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(func(r *ghttp.Request) { + r.SetCtx(gi18n.WithLanguage(r.Context(), "zh-CN")) + r.Middleware.Next() + }) + group.ALL("/", func(r *ghttp.Request) { + r.Response.WriteTplContent(`{#hello}{#world}!`) }) }) s.SetPort(8199) diff --git a/.example/net/ghttp/client/middleware/client.go b/.example/net/ghttp/client/middleware/client.go new file mode 100644 index 000000000..7ba07b4bf --- /dev/null +++ b/.example/net/ghttp/client/middleware/client.go @@ -0,0 +1,64 @@ +package main + +import ( + "bytes" + "fmt" + "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/internal/json" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/guid" + "github.com/gogf/gf/util/gutil" + "io/ioutil" + "net/http" +) + +const ( + appId = "123" + appSecret = "456" +) + +// 注入统一的接口签名参数 +func injectSignature(jsonContent []byte) []byte { + var m map[string]interface{} + _ = json.Unmarshal(jsonContent, &m) + if len(m) > 0 { + m["appid"] = appId + m["nonce"] = guid.S() + m["timestamp"] = gtime.Timestamp() + var ( + keyArray = garray.NewSortedStrArrayFrom(gutil.Keys(m)) + sigContent string + ) + keyArray.Iterator(func(k int, v string) bool { + sigContent += v + sigContent += gconv.String(m[v]) + return true + }) + m["signature"] = gmd5.MustEncryptString(gmd5.MustEncryptString(sigContent) + appSecret) + jsonContent, _ = json.Marshal(m) + } + return jsonContent +} + +func main() { + c := g.Client() + c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + bodyBytes, _ := ioutil.ReadAll(r.Body) + if len(bodyBytes) > 0 { + // 注入签名相关参数,修改Request原有的提交参数 + bodyBytes = injectSignature(bodyBytes) + r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + r.ContentLength = int64(len(bodyBytes)) + } + return c.Next(r) + }) + content := c.ContentJson().PostContent("http://127.0.0.1:8199/", g.Map{ + "name": "goframe", + "site": "https://goframe.org", + }) + fmt.Println(content) +} diff --git a/.example/net/ghttp/client/middleware/server.go b/.example/net/ghttp/client/middleware/server.go new file mode 100644 index 000000000..8770dd634 --- /dev/null +++ b/.example/net/ghttp/client/middleware/server.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +func main() { + s := g.Server() + s.Group("/", func(group *ghttp.RouterGroup) { + group.ALL("/", func(r *ghttp.Request) { + r.Response.Write(r.GetMap()) + }) + }) + s.SetPort(8199) + s.Run() +} diff --git a/.example/net/ghttp/server/request/json-xml/test2.go b/.example/net/ghttp/server/request/json-xml/test2.go index 5e3aed050..ced00e20d 100644 --- a/.example/net/ghttp/server/request/json-xml/test2.go +++ b/.example/net/ghttp/server/request/json-xml/test2.go @@ -25,7 +25,7 @@ func main() { //fmt.Println(r.GetBody()) if err := r.Parse(&req); err != nil { // Validation error. - if v, ok := err.(*gvalid.Error); ok { + if v, ok := err.(gvalid.Error); ok { r.Response.WriteJsonExit(RegisterRes{ Code: 1, Error: v.FirstString(), diff --git a/.example/net/ghttp/server/request/validation/validation2.go b/.example/net/ghttp/server/request/validation/validation2.go index ccee1e3f9..2800feab1 100644 --- a/.example/net/ghttp/server/request/validation/validation2.go +++ b/.example/net/ghttp/server/request/validation/validation2.go @@ -24,7 +24,7 @@ func main() { var req *RegisterReq if err := r.Parse(&req); err != nil { // Validation error. - if v, ok := err.(*gvalid.Error); ok { + if v, ok := err.(gvalid.Error); ok { r.Response.WriteJsonExit(RegisterRes{ Code: 1, Error: v.FirstString(), diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 24e6228db..8421900d5 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -339,7 +339,7 @@ func New(group ...string) (db DB, err error) { defer configs.RUnlock() if len(configs.config) < 1 { - return nil, gerror.New("empty database configuration") + return nil, gerror.New("database configuration is empty, please set the database configuration before using") } if _, ok := configs.config[groupName]; ok { if node, err := getConfigNodeByGroup(groupName, true); err == nil { @@ -358,13 +358,19 @@ func New(group ...string) (db DB, err error) { } return c.db, nil } else { - return nil, gerror.New(fmt.Sprintf(`unsupported database type "%s"`, node.Type)) + return nil, gerror.Newf( + `cannot find database driver for specified database type "%s", did you misspell type name "%s" or forget importing the database driver?`, + node.Type, node.Type, + ) } } else { return nil, err } } else { - return nil, gerror.New(fmt.Sprintf(`database configuration node "%s" is not found`, groupName)) + return nil, gerror.Newf( + `database configuration node "%s" is not found, did you misspell group name "%s" or miss the database configuration?`, + groupName, groupName, + ) } } diff --git a/frame/gins/gins_database.go b/frame/gins/gins_database.go index 2e92392ed..26e97b5fe 100644 --- a/frame/gins/gins_database.go +++ b/frame/gins/gins_database.go @@ -54,14 +54,14 @@ func Database(name ...string) gdb.DB { if exampleConfigFilePath, _ := Config().GetFilePath(exampleFileName); exampleConfigFilePath != "" { panic(gerror.Wrapf( err, - `configuration file "%s" not found, but found "%s", did you miss renaming the configuration example file?`, + `configuration file "%s" not found, but found "%s", did you miss renaming the example configuration file?`, Config().GetFileName(), exampleFileName, )) } else { panic(gerror.Wrapf( err, - `configuration file "%s" not found, did you miss the configuration file or the file name setting?`, + `configuration file "%s" not found, did you miss the configuration file or the misspell the configuration file name?`, Config().GetFileName(), )) } diff --git a/i18n/gi18n/gi18n.go b/i18n/gi18n/gi18n.go index bb2cc07e4..460239807 100644 --- a/i18n/gi18n/gi18n.go +++ b/i18n/gi18n/gi18n.go @@ -41,7 +41,6 @@ func TranslateFormat(ctx context.Context, format string, values ...interface{}) } // Translate translates with configured language and returns the translated content. -// The parameter specifies custom translation language ignoring configured language. func Translate(ctx context.Context, content string) string { return Instance().Translate(ctx, content) } diff --git a/i18n/gi18n/gi18n_manager.go b/i18n/gi18n/gi18n_manager.go index 9dc6a8639..0949c1f44 100644 --- a/i18n/gi18n/gi18n_manager.go +++ b/i18n/gi18n/gi18n_manager.go @@ -138,7 +138,6 @@ func (m *Manager) TranslateFormat(ctx context.Context, format string, values ... } // Translate translates with configured language. -// The parameter specifies custom translation language ignoring configured language. func (m *Manager) Translate(ctx context.Context, content string) string { m.init() m.mu.RLock() diff --git a/util/gvalid/gvalid.go b/util/gvalid/gvalid.go index 2a2e1316a..b9d234dae 100644 --- a/util/gvalid/gvalid.go +++ b/util/gvalid/gvalid.go @@ -189,7 +189,7 @@ var ( // string/map/struct/*struct. // The optional parameter `params` specifies the extra validation parameters for some rules // like: required-*、same、different, etc. -func Check(ctx context.Context, value interface{}, rules string, messages interface{}, params ...interface{}) *Error { +func Check(ctx context.Context, value interface{}, rules string, messages interface{}, params ...interface{}) Error { return defaultValidator.Ctx(ctx).Check(value, rules, messages, params...) } @@ -198,7 +198,7 @@ func Check(ctx context.Context, value interface{}, rules string, messages interf // The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. // The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func CheckMap(ctx context.Context, params interface{}, rules interface{}, messages ...CustomMsg) *Error { +func CheckMap(ctx context.Context, params interface{}, rules interface{}, messages ...CustomMsg) Error { return defaultValidator.Ctx(ctx).CheckMap(params, rules, messages...) } @@ -208,7 +208,7 @@ func CheckMap(ctx context.Context, params interface{}, rules interface{}, messag // The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. // The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func CheckStruct(ctx context.Context, object interface{}, rules interface{}, messages ...CustomMsg) *Error { +func CheckStruct(ctx context.Context, object interface{}, rules interface{}, messages ...CustomMsg) Error { return defaultValidator.Ctx(ctx).CheckStruct(object, rules, messages...) } @@ -218,7 +218,7 @@ func CheckStruct(ctx context.Context, object interface{}, rules interface{}, mes // The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. // The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func CheckStructWithParamMap(ctx context.Context, object interface{}, paramMap interface{}, rules interface{}, messages ...CustomMsg) *Error { +func CheckStructWithParamMap(ctx context.Context, object interface{}, paramMap interface{}, rules interface{}, messages ...CustomMsg) Error { return defaultValidator.Ctx(ctx).CheckStructWithParamMap(object, paramMap, rules, messages...) } diff --git a/util/gvalid/gvalid_error.go b/util/gvalid/gvalid_error.go index 7a2a30141..c55da3f56 100644 --- a/util/gvalid/gvalid_error.go +++ b/util/gvalid/gvalid_error.go @@ -14,19 +14,28 @@ import ( ) // Error is the validation error for validation result. -type Error struct { - rules []string // Rules by sequence, which is used for keeping error sequence. - errors ErrorMap // Error map. - firstKey string // The first error rule key(nil in default). - firstItem map[string]string // The first error rule value(nil in default). +type Error interface { + Current() error + Error() string + FirstItem() (key string, messages map[string]string) + FirstRule() (rule string, err string) + FirstString() (err string) + Map() map[string]string + Maps() map[string]map[string]string + String() string + Strings() (errs []string) } -// ErrorMap is the validation error map: -// map[field]map[rule]message -type ErrorMap map[string]map[string]string +// validationError is the validation error for validation result. +type validationError struct { + rules []string // Rules by sequence, which is used for keeping error sequence. + errors map[string]map[string]string // Error map:map[field]map[rule]message + firstKey string // The first error rule key(nil in default). + firstItem map[string]string // The first error rule value(nil in default). +} // newError creates and returns a validation error. -func newError(rules []string, errors map[string]map[string]string) *Error { +func newError(rules []string, errors map[string]map[string]string) *validationError { for field, m := range errors { for k, v := range m { v = strings.Replace(v, ":attribute", field, -1) @@ -36,14 +45,14 @@ func newError(rules []string, errors map[string]map[string]string) *Error { } errors[field] = m } - return &Error{ + return &validationError{ rules: rules, errors: errors, } } // newErrorStr creates and returns a validation error by string. -func newErrorStr(key, err string) *Error { +func newErrorStr(key, err string) *validationError { return newError(nil, map[string]map[string]string{ "__gvalid__": { key: err, @@ -52,7 +61,7 @@ func newErrorStr(key, err string) *Error { } // Map returns the first error message as map. -func (e *Error) Map() map[string]string { +func (e *validationError) Map() map[string]string { if e == nil { return map[string]string{} } @@ -61,7 +70,7 @@ func (e *Error) Map() map[string]string { } // Maps returns all error messages as map. -func (e *Error) Maps() ErrorMap { +func (e *validationError) Maps() map[string]map[string]string { if e == nil { return nil } @@ -69,7 +78,7 @@ func (e *Error) Maps() ErrorMap { } // FirstItem returns the field name and error messages for the first validation rule error. -func (e *Error) FirstItem() (key string, messages map[string]string) { +func (e *validationError) FirstItem() (key string, messages map[string]string) { if e == nil { return "", map[string]string{} } @@ -97,7 +106,7 @@ func (e *Error) FirstItem() (key string, messages map[string]string) { } // FirstRule returns the first error rule and message string. -func (e *Error) FirstRule() (rule string, err string) { +func (e *validationError) FirstRule() (rule string, err string) { if e == nil { return "", "" } @@ -127,7 +136,7 @@ func (e *Error) FirstRule() (rule string, err string) { // FirstString returns the first error message as string. // Note that the returned message might be different if it has no sequence. -func (e *Error) FirstString() (err string) { +func (e *validationError) FirstString() (err string) { if e == nil { return "" } @@ -136,7 +145,7 @@ func (e *Error) FirstString() (err string) { } // Current is alis of FirstString, which implements interface gerror.ApiCurrent. -func (e *Error) Current() error { +func (e *validationError) Current() error { if e == nil { return nil } @@ -145,7 +154,7 @@ func (e *Error) Current() error { } // String returns all error messages as string, multiple error messages joined using char ';'. -func (e *Error) String() string { +func (e *validationError) String() string { if e == nil { return "" } @@ -153,7 +162,7 @@ func (e *Error) String() string { } // Error implements interface of error.Error. -func (e *Error) Error() string { +func (e *validationError) Error() string { if e == nil { return "" } @@ -161,7 +170,7 @@ func (e *Error) Error() string { } // Strings returns all error messages as string array. -func (e *Error) Strings() (errs []string) { +func (e *validationError) Strings() (errs []string) { if e == nil { return []string{} } diff --git a/util/gvalid/gvalid_validator_check.go b/util/gvalid/gvalid_validator_check.go index c37e4c66f..86e367cce 100644 --- a/util/gvalid/gvalid_validator_check.go +++ b/util/gvalid/gvalid_validator_check.go @@ -35,12 +35,12 @@ type apiTime interface { // string/map/struct/*struct. // The optional parameter `params` specifies the extra validation parameters for some rules // like: required-*、same、different, etc. -func (v *Validator) Check(value interface{}, rules string, messages interface{}, paramMap ...interface{}) *Error { +func (v *Validator) Check(value interface{}, rules string, messages interface{}, paramMap ...interface{}) Error { return v.doCheck("", value, rules, messages, paramMap...) } // doCheck does the really rules validation for single key-value. -func (v *Validator) doCheck(key string, value interface{}, rules string, messages interface{}, paramMap ...interface{}) *Error { +func (v *Validator) doCheck(key string, value interface{}, rules string, messages interface{}, paramMap ...interface{}) Error { // If there's no validation rules, it does nothing and returns quickly. if rules == "" { return nil @@ -136,7 +136,7 @@ func (v *Validator) doCheck(key string, value interface{}, rules string, message index++ } if len(errorMsgArray) > 0 { - return newError([]string{rules}, ErrorMap{ + return newError([]string{rules}, map[string]map[string]string{ key: errorMsgArray, }) } diff --git a/util/gvalid/gvalid_validator_check_map.go b/util/gvalid/gvalid_validator_check_map.go index 3229e2752..2f24759a3 100644 --- a/util/gvalid/gvalid_validator_check_map.go +++ b/util/gvalid/gvalid_validator_check_map.go @@ -16,7 +16,7 @@ import ( // The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. // The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Error { +func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) Error { // If there's no validation rules, it does nothing and returns quickly. if params == nil || rules == nil { return nil @@ -25,7 +25,7 @@ func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ... checkRules = make(map[string]string) customMsgs = make(CustomMsg) errorRules = make([]string, 0) - errorMaps = make(ErrorMap) + errorMaps = make(map[string]map[string]string) ) switch v := rules.(type) { // Sequence tag: []sequence tag diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 5ed23c45e..abb4c7829 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -16,10 +16,10 @@ import ( // CheckStruct validates struct and returns the error result. // // The parameter `object` should be type of struct/*struct. -// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result +// The parameter `customRules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. -// The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func (v *Validator) CheckStruct(object interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) *Error { +// The optional parameter `customErrorMessageMap` specifies the custom error messages for specified keys and rules. +func (v *Validator) CheckStruct(object interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) Error { var message CustomMsg if len(customErrorMessageMap) > 0 { message = customErrorMessageMap[0] @@ -36,10 +36,11 @@ func (v *Validator) CheckStruct(object interface{}, customRules interface{}, cus // CheckStructWithParamMap validates struct with given parameter map and returns the error result. // // The parameter `object` should be type of struct/*struct. -// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result +// The parameter `paramMap` should be type of map, which specifies the parameter map used in validation. +// The parameter `customRules` can be type of []string/map[string]string. It supports sequence in error result // if `rules` is type of []string. -// The optional parameter `messages` specifies the custom error messages for specified keys and rules. -func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) *Error { +// The optional parameter `customErrorMessageMap` specifies the custom error messages for specified keys and rules. +func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) Error { var message CustomMsg if len(customErrorMessageMap) > 0 { message = customErrorMessageMap[0] @@ -53,10 +54,10 @@ func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interfa }) } -func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapInput) *Error { +func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapInput) Error { var ( // Returning error. - errorMaps = make(ErrorMap) + errorMaps = make(map[string]map[string]string) ) fieldMap, err := structs.FieldMap(input.Object, aliasNameTagPriority, true) if err != nil { @@ -77,7 +78,7 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn recursiveInput.Object = field.Value if err := v.doCheckStructWithParamMap(&recursiveInput); err != nil { // It merges the errors into single error map. - for k, m := range err.errors { + for k, m := range err.(*validationError).errors { errorMaps[k] = m } } @@ -158,7 +159,8 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn } } } - + // Merge the custom validation rules with rules in struct tag. + // The custom rules has the most high priority that can overwrite the struct tag rules. for _, field := range tagField { fieldName := field.Name() // sequence tag == struct tag diff --git a/util/gvalid/gvalid_z_example_test.go b/util/gvalid/gvalid_z_example_test.go index fac360194..3f7648bfe 100644 --- a/util/gvalid/gvalid_z_example_test.go +++ b/util/gvalid/gvalid_z_example_test.go @@ -187,4 +187,6 @@ func ExampleRegisterRule_OverwriteRequired() { // It's required // rule deleted // It's required + // + // } diff --git a/util/gvalid/gvalid_z_unit_custom_rule_test.go b/util/gvalid/gvalid_z_unit_custom_rule_test.go index 326c42ebd..e4a7f45a6 100644 --- a/util/gvalid/gvalid_z_unit_custom_rule_test.go +++ b/util/gvalid/gvalid_z_unit_custom_rule_test.go @@ -78,7 +78,7 @@ func Test_CustomRule2(t *testing.T) { gtest.C(t, func(t *gtest.T) { errStr := "data map should not be empty" t.Assert(gvalid.Check(context.TODO(), g.Map{}, rule, errStr).String(), errStr) - t.Assert(gvalid.Check(context.TODO(), g.Map{"k": "v"}, rule, errStr).String(), nil) + t.Assert(gvalid.Check(context.TODO(), g.Map{"k": "v"}, rule, errStr), nil) }) // Error with struct validation. gtest.C(t, func(t *gtest.T) { @@ -121,8 +121,8 @@ func Test_CustomRule_AllowEmpty(t *testing.T) { // Check. gtest.C(t, func(t *gtest.T) { errStr := "error" - t.Assert(gvalid.Check(context.TODO(), "", rule, errStr).String(), "") - t.Assert(gvalid.Check(context.TODO(), "gf", rule, errStr).String(), "") + t.Assert(gvalid.Check(context.TODO(), "", rule, errStr), nil) + t.Assert(gvalid.Check(context.TODO(), "gf", rule, errStr), nil) t.Assert(gvalid.Check(context.TODO(), "gf2", rule, errStr).String(), errStr) }) // Error with struct validation. @@ -136,7 +136,7 @@ func Test_CustomRule_AllowEmpty(t *testing.T) { Data: "123456", } err := gvalid.CheckStruct(context.TODO(), st, nil) - t.Assert(err.String(), "") + t.Assert(err, nil) }) // No error with struct validation. gtest.C(t, func(t *gtest.T) { diff --git a/util/gvalid/gvalid_z_unit_i18n_test.go b/util/gvalid/gvalid_z_unit_i18n_test.go index bb27a3f4e..16bc2d809 100644 --- a/util/gvalid/gvalid_z_unit_i18n_test.go +++ b/util/gvalid/gvalid_z_unit_i18n_test.go @@ -18,7 +18,7 @@ import ( func TestValidator_I18n(t *testing.T) { var ( - err *gvalid.Error + err gvalid.Error i18nManager = gi18n.New(gi18n.Options{Path: gdebug.TestDataPath("i18n")}) ctxCn = gi18n.WithLanguage(context.TODO(), "cn") validator = gvalid.New().I18n(i18nManager)