diff --git a/util/guid/guid.go b/util/guid/guid.go index 59cca7b6a..88cc8e7f1 100644 --- a/util/guid/guid.go +++ b/util/guid/guid.go @@ -4,11 +4,126 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package guid provides simple and high performance unique id generation functionality. -// -// Unique String ID: -// PLEASE VERY NOTE: -// This package only provides unique number generation for simple, convenient and most common -// usage purpose, but does not provide strict global unique number generation. Please refer -// to UUID algorithm for global unique number generation if necessary. package guid + +import ( + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/encoding/ghash" + "github.com/gogf/gf/net/gipv4" + "github.com/gogf/gf/util/grand" + "os" + "strconv" + "time" +) + +const ( + sequenceMax = uint32(46655) // Sequence max("zzz"). + randomStrBase = "0123456789abcdefghijklmnopqrstuvwxyz" // Random chars string(36 bytes). +) + +var ( + sequence gtype.Uint32 // Sequence for unique purpose of current process. + macAddrStr = "0000000" // MAC addresses hash result in 7 bytes. + processIdStr = "0000" // Process id in 4 bytes. +) + +// init initializes several fixed local variable. +func init() { + // MAC addresses hash result in 7 bytes. + macs, _ := gipv4.GetMacArray() + if len(macs) > 0 { + var macAddrBytes []byte + for _, mac := range macs { + macAddrBytes = append(macAddrBytes, []byte(mac)...) + } + b := []byte{'0', '0', '0', '0', '0', '0', '0'} + s := strconv.FormatUint(uint64(ghash.DJBHash(macAddrBytes)), 36) + copy(b, s) + macAddrStr = string(b) + } + // Process id in 4 bytes. + { + b := []byte{'0', '0', '0', '0'} + s := strconv.FormatInt(int64(os.Getpid()), 36) + copy(b, s) + processIdStr = string(b) + } +} + +// S creates and returns a global unique string in 32 bytes that meets most common +// usages without strict UUID algorithm. It returns a unique string using default +// unique algorithm if no `data` is given. +// +// The specified `data` can be no more than 2 parts. No matter how long each of the +// `data` size is, each of them will be hashed into 7 bytes as part of the result. +// If given `data` parts is less than 2, the leftover size of the result bytes will +// be token by random string. +// +// The returned string is composed with: +// 1. Default: MAC(7) + PID(4) + TimestampNano(12) + Sequence(3) + RandomString(6) +// 2. CustomData: Data(7/14) + TimestampNano(12) + Sequence(3) + RandomString(3/10) +// +// Note that: +// 1. The returned length is fixed to 32 bytes for performance purpose. +// 2. The custom parameter `data` composed should have unique attribute in your +// business situation. +func S(data ...[]byte) string { + var ( + b = make([]byte, 32) + nanoStr = strconv.FormatInt(time.Now().UnixNano(), 36) + ) + if len(data) == 0 { + copy(b, macAddrStr) + copy(b[7:], processIdStr) + copy(b[11:], nanoStr) + copy(b[23:], getSequence()) + copy(b[26:], getRandomStr(6)) + } else if len(data) <= 2 { + n := 0 + for i, v := range data { + // Ignore empty data item bytes. + if len(v) > 0 { + copy(b[i*7:], getDataHashStr(v)) + n += 7 + } + } + copy(b[n:], nanoStr) + copy(b[n+12:], getSequence()) + copy(b[n+12+3:], getRandomStr(32-n-12-3)) + } else { + panic("too many data parts, it should be no more than 2 parts") + } + return string(b) +} + +// getSequence increases and returns the sequence string in 3 bytes. +// The sequence is less than "zzz"(46655). +func getSequence() []byte { + b := []byte{'0', '0', '0'} + s := strconv.FormatUint(uint64(sequence.Add(1)%sequenceMax), 36) + copy(b, s) + return b +} + +// getRandomStr randomly picks and returns `n` count of chars from randomStrBase. +func getRandomStr(n int) []byte { + if n <= 0 { + return []byte{} + } + var ( + b = make([]byte, n) + numberBytes = grand.B(n) + ) + for i := range b { + b[i] = randomStrBase[numberBytes[i]%36] + } + return b +} + +// getDataHashStr creates and returns hash bytes in 7 bytes with given data bytes. +func getDataHashStr(data []byte) []byte { + b := []byte{'0', '0', '0', '0', '0', '0', '0'} + s := strconv.FormatUint(uint64(ghash.DJBHash(data)), 36) + copy(b, s) + return b +} diff --git a/util/guid/guid_string.go b/util/guid/guid_string.go deleted file mode 100644 index e8386aeb8..000000000 --- a/util/guid/guid_string.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package guid - -import ( - "github.com/gogf/gf/container/gtype" - "github.com/gogf/gf/encoding/ghash" - "github.com/gogf/gf/net/gipv4" - "github.com/gogf/gf/util/grand" - "os" - "strconv" - "time" -) - -const ( - sequenceMax = uint32(46655) // Sequence max("zzz"). - randomStrBase = "0123456789abcdefghijklmnopqrstuvwxyz" // Random chars string(36 bytes). -) - -var ( - sequence gtype.Uint32 // Sequence for unique purpose of current process. - macAddrStr = "0000000" // MAC addresses hash result in 7 bytes. - processIdStr = "0000" // Process id in 4 bytes. -) - -// init initializes several fixed local variable. -func init() { - // MAC addresses hash result in 7 bytes. - macs, _ := gipv4.GetMacArray() - if len(macs) > 0 { - var macAddrBytes []byte - for _, mac := range macs { - macAddrBytes = append(macAddrBytes, []byte(mac)...) - } - b := []byte{'0', '0', '0', '0', '0', '0', '0'} - s := strconv.FormatUint(uint64(ghash.DJBHash(macAddrBytes)), 36) - copy(b, s) - macAddrStr = string(b) - } - // Process id in 4 bytes. - { - b := []byte{'0', '0', '0', '0'} - s := strconv.FormatInt(int64(os.Getpid()), 36) - copy(b, s) - processIdStr = string(b) - } -} - -// S creates and returns a global unique string in 32 bytes that meets most common -// usages without strict UUID algorithm. It returns an unique string using default -// unique algorithm if no `data` is given. -// -// The specified `data` can be no more than 2 parts. No matter how long each of the -// `data` size is, each of them will be hashed into 7 bytes as part of the result. -// If given `data` parts is less than 2, the leftover size of the result bytes will -// be token by random string. -// -// The returned string is composed with: -// 1. Default: MAC(7) + PID(4) + TimestampNano(12) + Sequence(3) + RandomString(6) -// 2. CustomData: Data(7/14) + TimestampNano(12) + Sequence(3) + RandomString(3/10) -// -// Note that: -// 1. The returned length is fixed to 32 bytes for performance purpose. -// 2. The custom parameter `data` composed should have unique attribute in your -// business situation. -func S(data ...[]byte) string { - var ( - b = make([]byte, 32) - nanoStr = strconv.FormatInt(time.Now().UnixNano(), 36) - ) - if len(data) == 0 { - copy(b, macAddrStr) - copy(b[7:], processIdStr) - copy(b[11:], nanoStr) - copy(b[23:], getSequence()) - copy(b[26:], getRandomStr(6)) - } else if len(data) <= 2 { - n := 0 - for i, v := range data { - // Ignore empty data item bytes. - if len(v) > 0 { - copy(b[i*7:], getDataHashStr(v)) - n += 7 - } - } - copy(b[n:], nanoStr) - copy(b[n+12:], getSequence()) - copy(b[n+12+3:], getRandomStr(32-n-12-3)) - } else { - panic("too many data parts, it should be no more than 2 parts") - } - return string(b) -} - -// getSequence increases and returns the sequence string in 3 bytes. -// The sequence is less than "zzz"(46655). -func getSequence() []byte { - b := []byte{'0', '0', '0'} - s := strconv.FormatUint(uint64(sequence.Add(1)%sequenceMax), 36) - copy(b, s) - return b -} - -// getRandomStr randomly picks and returns `n` count of chars from randomStrBase. -func getRandomStr(n int) []byte { - if n <= 0 { - return []byte{} - } - var ( - b = make([]byte, n) - numberBytes = grand.B(n) - ) - for i := range b { - b[i] = randomStrBase[numberBytes[i]%36] - } - return b -} - -// getDataHashStr creates and returns hash bytes in 7 bytes with given data bytes. -func getDataHashStr(data []byte) []byte { - b := []byte{'0', '0', '0', '0', '0', '0', '0'} - s := strconv.FormatUint(uint64(ghash.DJBHash(data)), 36) - copy(b, s) - return b -} diff --git a/util/gvalid/gvalid.go b/util/gvalid/gvalid.go index e15cc39c7..e449aa732 100644 --- a/util/gvalid/gvalid.go +++ b/util/gvalid/gvalid.go @@ -253,7 +253,7 @@ func CheckValue(ctx context.Context, value interface{}, rules string, messages i if len(params) > 0 { data = params[0] } - return defaultValidator.Ctx(ctx).Rules(rules).Data(data).Messages(messages).CheckValue(value) + return defaultValidator.Rules(rules).Data(data).Messages(messages).CheckValue(ctx, value) } // CheckMap validates map and returns the error result. It returns nil if with successful validation. @@ -266,7 +266,7 @@ func CheckMap(ctx context.Context, params interface{}, rules interface{}, messag if len(messages) > 0 { customErrorMessages = messages[0] } - return defaultValidator.Ctx(ctx).Rules(rules).Messages(customErrorMessages).CheckMap(params) + return defaultValidator.Rules(rules).Messages(customErrorMessages).CheckMap(ctx, params) } // CheckStruct validates struct and returns the error result. @@ -280,7 +280,7 @@ func CheckStruct(ctx context.Context, object interface{}, rules interface{}, mes if len(messages) > 0 { customErrorMessages = messages[0] } - return defaultValidator.Ctx(ctx).Rules(rules).Messages(customErrorMessages).CheckStruct(object) + return defaultValidator.Rules(rules).Messages(customErrorMessages).CheckStruct(ctx, object) } // CheckStructWithData validates struct with given parameter map and returns the error result. @@ -294,7 +294,7 @@ func CheckStructWithData(ctx context.Context, object interface{}, data interface if len(messages) > 0 { customErrorMessages = messages[0] } - return defaultValidator.Ctx(ctx).Data(data).Rules(rules).Messages(customErrorMessages).CheckStruct(object) + return defaultValidator.Data(data).Rules(rules).Messages(customErrorMessages).CheckStruct(ctx, object) } // parseSequenceTag parses one sequence tag to field, rule and error message. diff --git a/util/gvalid/gvalid_custom_rule.go b/util/gvalid/gvalid_custom_rule.go index d1e3589bb..aa2fc9ba4 100644 --- a/util/gvalid/gvalid_custom_rule.go +++ b/util/gvalid/gvalid_custom_rule.go @@ -9,6 +9,7 @@ package gvalid import "context" // RuleFunc is the custom function for data validation. +// // The parameter `rule` specifies the validation rule string, like "required", "between:1,100", etc. // The parameter `value` specifies the value for this rule to validate. // The parameter `message` specifies the custom error message or configured i18n message for this rule. diff --git a/util/gvalid/gvalid_error.go b/util/gvalid/gvalid_error.go index 5fe38875c..c8e87dff2 100644 --- a/util/gvalid/gvalid_error.go +++ b/util/gvalid/gvalid_error.go @@ -182,7 +182,7 @@ func (e *validationError) FirstString() (err string) { return } -// Current is alis of FirstString, which implements interface gerror.ApiCurrent. +// Current is alis of FirstString, which implements interface gerror.iCurrent. func (e *validationError) Current() error { if e == nil { return nil diff --git a/util/gvalid/gvalid_validator.go b/util/gvalid/gvalid_validator.go index d050dc237..4b8fa2f64 100644 --- a/util/gvalid/gvalid_validator.go +++ b/util/gvalid/gvalid_validator.go @@ -7,13 +7,11 @@ package gvalid import ( - "context" "github.com/gogf/gf/i18n/gi18n" ) // Validator is the validation manager for chaining operations. type Validator struct { - ctx context.Context // Context containing custom context variables. i18nManager *gi18n.Manager // I18n manager for error message translation. key string // Single validation key. value interface{} // Single validation value. @@ -28,7 +26,6 @@ type Validator struct { // New creates and returns a new Validator. func New() *Validator { return &Validator{ - ctx: context.TODO(), // Initialize an empty context. i18nManager: gi18n.Instance(), // Use default i18n manager. ruleFuncMap: make(map[string]RuleFunc), // Custom rule function storing map. } @@ -48,13 +45,6 @@ func (v *Validator) I18n(i18nManager *gi18n.Manager) *Validator { return newValidator } -// Ctx is a chaining operation function, which sets the context for next validation. -func (v *Validator) Ctx(ctx context.Context) *Validator { - newValidator := v.Clone() - newValidator.ctx = ctx - return newValidator -} - // Bail sets the mark for stopping validation after the first validation error. func (v *Validator) Bail() *Validator { newValidator := v.Clone() diff --git a/util/gvalid/gvalid_validator_check_map.go b/util/gvalid/gvalid_validator_check_map.go index 9db900232..fd8a76e9f 100644 --- a/util/gvalid/gvalid_validator_check_map.go +++ b/util/gvalid/gvalid_validator_check_map.go @@ -7,6 +7,7 @@ package gvalid import ( + "context" "github.com/gogf/gf/errors/gcode" "github.com/gogf/gf/util/gconv" "strings" @@ -14,11 +15,11 @@ import ( // CheckMap validates map and returns the error result. It returns nil if with successful validation. // The parameter `params` should be type of map. -func (v *Validator) CheckMap(params interface{}) Error { - return v.doCheckMap(params) +func (v *Validator) CheckMap(ctx context.Context, params interface{}) Error { + return v.doCheckMap(ctx, params) } -func (v *Validator) doCheckMap(params interface{}) Error { +func (v *Validator) doCheckMap(ctx context.Context, params interface{}) Error { // If there's no validation rules, it does nothing and returns quickly. if params == nil || v.rules == nil { return nil @@ -105,7 +106,7 @@ func (v *Validator) doCheckMap(params interface{}) Error { value = valueItem } // It checks each rule and its value in loop. - if validatedError := v.doCheckValue(doCheckValueInput{ + if validatedError := v.doCheckValue(ctx, doCheckValueInput{ Name: checkRuleItem.Name, Value: value, Rule: checkRuleItem.Rule, diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index c70a8f077..5f7b95abb 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -7,6 +7,7 @@ package gvalid import ( + "context" "github.com/gogf/gf/errors/gcode" "github.com/gogf/gf/internal/structs" "github.com/gogf/gf/util/gconv" @@ -16,14 +17,14 @@ import ( // CheckStruct validates struct and returns the error result. // The parameter `object` should be type of struct/*struct. -func (v *Validator) CheckStruct(object interface{}) Error { - return v.doCheckStruct(object) +func (v *Validator) CheckStruct(ctx context.Context, object interface{}) Error { + return v.doCheckStruct(ctx, object) } -func (v *Validator) doCheckStruct(object interface{}) Error { +func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error { var ( errorMaps = make(map[string]map[string]string) // Returning error. - fieldToAliasNameMap = make(map[string]string) // Field name to alias name map. + fieldToAliasNameMap = make(map[string]string) // Field names to alias name map. ) fieldMap, err := structs.FieldMap(structs.FieldMapInput{ Pointer: object, @@ -33,7 +34,7 @@ func (v *Validator) doCheckStruct(object interface{}) Error { if err != nil { return newErrorStr(internalObjectErrRuleName, err.Error()) } - // It checks the struct recursively the its attribute is an embedded struct. + // It checks the struct recursively if its attribute is an embedded struct. for _, field := range fieldMap { if field.IsEmbedded() { // No validation interface implements check. @@ -43,7 +44,7 @@ func (v *Validator) doCheckStruct(object interface{}) Error { if _, ok := field.TagLookup(noValidationTagName); ok { continue } - if err := v.doCheckStruct(field.Value); err != nil { + if err := v.doCheckStruct(ctx, field.Value); err != nil { // It merges the errors into single error map. for k, m := range err.(*validationError).errors { errorMaps[k] = m @@ -244,7 +245,7 @@ func (v *Validator) doCheckStruct(object interface{}) Error { for _, checkRuleItem := range checkRules { _, value = gutil.MapPossibleItemByKey(inputParamMap, checkRuleItem.Name) // It checks each rule and its value in loop. - if validatedError := v.doCheckValue(doCheckValueInput{ + if validatedError := v.doCheckValue(ctx, doCheckValueInput{ Name: checkRuleItem.Name, Value: value, Rule: checkRuleItem.Rule, diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 50a483cbf..4507f8c55 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -7,6 +7,7 @@ package gvalid import ( + "context" "github.com/gogf/gf/errors/gcode" "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/text/gstr" @@ -30,8 +31,8 @@ type iTime interface { // CheckValue checks single value with specified rules. // It returns nil if successful validation. -func (v *Validator) CheckValue(value interface{}) Error { - return v.doCheckValue(doCheckValueInput{ +func (v *Validator) CheckValue(ctx context.Context, value interface{}) Error { + return v.doCheckValue(ctx, doCheckValueInput{ Name: "", Value: value, Rule: gconv.String(v.rules), @@ -51,7 +52,7 @@ type doCheckValueInput struct { } // doCheckSingleValue does the really rules validation for single key-value. -func (v *Validator) doCheckValue(input doCheckValueInput) Error { +func (v *Validator) doCheckValue(ctx context.Context, input doCheckValueInput) Error { // If there's no validation rules, it does nothing and returns quickly. if input.Rule == "" { return nil @@ -131,8 +132,8 @@ func (v *Validator) doCheckValue(input doCheckValueInput) Error { customRuleFunc = v.getRuleFunc(ruleKey) if customRuleFunc != nil { // It checks custom validation rules with most priority. - message := v.getErrorMessageByRule(ruleKey, customMsgMap) - if err := customRuleFunc(v.ctx, ruleItems[index], input.Value, message, input.DataRaw); err != nil { + message := v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) + if err := customRuleFunc(ctx, ruleItems[index], input.Value, message, input.DataRaw); err != nil { match = false errorMsgArray[ruleKey] = err.Error() } else { @@ -140,15 +141,18 @@ func (v *Validator) doCheckValue(input doCheckValueInput) Error { } } else { // It checks build-in validation rules if there's no custom rule. - match, err = v.doCheckBuildInRules(doCheckBuildInRulesInput{ - Index: index, - Value: input.Value, - RuleKey: ruleKey, - RulePattern: rulePattern, - RuleItems: ruleItems, - DataMap: input.DataMap, - CustomMsgMap: customMsgMap, - }) + match, err = v.doCheckBuildInRules( + ctx, + doCheckBuildInRulesInput{ + Index: index, + Value: input.Value, + RuleKey: ruleKey, + RulePattern: rulePattern, + RuleItems: ruleItems, + DataMap: input.DataMap, + CustomMsgMap: customMsgMap, + }, + ) if !match && err != nil { errorMsgArray[ruleKey] = err.Error() } @@ -159,7 +163,7 @@ func (v *Validator) doCheckValue(input doCheckValueInput) Error { // It does nothing if the error message for this rule // is already set in previous validation. if _, ok := errorMsgArray[ruleKey]; !ok { - errorMsgArray[ruleKey] = v.getErrorMessageByRule(ruleKey, customMsgMap) + errorMsgArray[ruleKey] = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) } // If it is with error and there's bail rule, // it then does not continue validating for left rules. @@ -170,9 +174,13 @@ func (v *Validator) doCheckValue(input doCheckValueInput) Error { index++ } if len(errorMsgArray) > 0 { - return newError(gcode.CodeValidationFailed, []fieldRule{{Name: input.Name, Rule: input.Rule}}, map[string]map[string]string{ - input.Name: errorMsgArray, - }) + return newError( + gcode.CodeValidationFailed, + []fieldRule{{Name: input.Name, Rule: input.Rule}}, + map[string]map[string]string{ + input.Name: errorMsgArray, + }, + ) } return nil } @@ -187,7 +195,7 @@ type doCheckBuildInRulesInput struct { CustomMsgMap map[string]string } -func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match bool, err error) { +func (v *Validator) doCheckBuildInRules(ctx context.Context, input doCheckBuildInRulesInput) (match bool, err error) { valueStr := gconv.String(input.Value) switch input.RuleKey { // Required rules. @@ -208,7 +216,7 @@ func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match b "min-length", "max-length", "size": - if msg := v.checkLength(valueStr, input.RuleKey, input.RulePattern, input.CustomMsgMap); msg != "" { + if msg := v.checkLength(ctx, valueStr, input.RuleKey, input.RulePattern, input.CustomMsgMap); msg != "" { return match, gerror.NewOption(gerror.Option{ Text: msg, Code: gcode.CodeValidationFailed, @@ -222,7 +230,7 @@ func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match b "min", "max", "between": - if msg := v.checkRange(valueStr, input.RuleKey, input.RulePattern, input.CustomMsgMap); msg != "" { + if msg := v.checkRange(ctx, valueStr, input.RuleKey, input.RulePattern, input.CustomMsgMap); msg != "" { return match, gerror.NewOption(gerror.Option{ Text: msg, Code: gcode.CodeValidationFailed, @@ -260,7 +268,7 @@ func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match b match = true } else { var msg string - msg = v.getErrorMessageByRule(input.RuleKey, input.CustomMsgMap) + msg = v.getErrorMessageByRule(ctx, input.RuleKey, input.CustomMsgMap) msg = strings.Replace(msg, ":format", input.RulePattern, -1) return match, gerror.NewOption(gerror.Option{ Text: msg, @@ -278,7 +286,7 @@ func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match b } if !match { var msg string - msg = v.getErrorMessageByRule(input.RuleKey, input.CustomMsgMap) + msg = v.getErrorMessageByRule(ctx, input.RuleKey, input.CustomMsgMap) msg = strings.Replace(msg, ":field", input.RulePattern, -1) return match, gerror.NewOption(gerror.Option{ Text: msg, @@ -297,7 +305,7 @@ func (v *Validator) doCheckBuildInRules(input doCheckBuildInRulesInput) (match b } if !match { var msg string - msg = v.getErrorMessageByRule(input.RuleKey, input.CustomMsgMap) + msg = v.getErrorMessageByRule(ctx, input.RuleKey, input.CustomMsgMap) msg = strings.Replace(msg, ":field", input.RulePattern, -1) return match, gerror.NewOption(gerror.Option{ Text: msg, diff --git a/util/gvalid/gvalid_validator_message.go b/util/gvalid/gvalid_validator_message.go index 7701e5f96..5a14106a2 100644 --- a/util/gvalid/gvalid_validator_message.go +++ b/util/gvalid/gvalid_validator_message.go @@ -6,27 +6,29 @@ package gvalid +import "context" + // getErrorMessageByRule retrieves and returns the error message for specified rule. // It firstly retrieves the message from custom message map, and then checks i18n manager, // it returns the default error message if it's not found in custom message map or i18n manager. -func (v *Validator) getErrorMessageByRule(ruleKey string, customMsgMap map[string]string) string { +func (v *Validator) getErrorMessageByRule(ctx context.Context, ruleKey string, customMsgMap map[string]string) string { content := customMsgMap[ruleKey] if content != "" { // I18n translation. - i18nContent := v.i18nManager.GetContent(v.ctx, content) + i18nContent := v.i18nManager.GetContent(ctx, content) if i18nContent != "" { return i18nContent } return content } // Retrieve default message according to certain rule. - content = v.i18nManager.GetContent(v.ctx, ruleMessagePrefixForI18n+ruleKey) + content = v.i18nManager.GetContent(ctx, ruleMessagePrefixForI18n+ruleKey) if content == "" { content = defaultMessages[ruleKey] } // If there's no configured rule message, it uses default one. if content == "" { - content = v.i18nManager.GetContent(v.ctx, ruleMessagePrefixForI18n+internalDefaultRuleName) + content = v.i18nManager.GetContent(ctx, ruleMessagePrefixForI18n+internalDefaultRuleName) if content == "" { content = defaultMessages[internalDefaultRuleName] } diff --git a/util/gvalid/gvalid_validator_rule_length.go b/util/gvalid/gvalid_validator_rule_length.go index 7bd5b188e..2af3a0bb9 100644 --- a/util/gvalid/gvalid_validator_rule_length.go +++ b/util/gvalid/gvalid_validator_rule_length.go @@ -7,6 +7,7 @@ package gvalid import ( + "context" "github.com/gogf/gf/util/gconv" "strconv" "strings" @@ -15,7 +16,7 @@ import ( // checkLength checks `value` using length rules. // The length is calculated using unicode string, which means one chinese character or letter // both has the length of 1. -func (v *Validator) checkLength(value, ruleKey, ruleVal string, customMsgMap map[string]string) string { +func (v *Validator) checkLength(ctx context.Context, value, ruleKey, ruleVal string, customMsgMap map[string]string) string { var ( msg = "" runeArray = gconv.Runes(value) @@ -39,7 +40,7 @@ func (v *Validator) checkLength(value, ruleKey, ruleVal string, customMsgMap map } } if valueLen < min || valueLen > max { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.Itoa(min), -1) msg = strings.Replace(msg, ":max", strconv.Itoa(max), -1) return msg @@ -48,21 +49,21 @@ func (v *Validator) checkLength(value, ruleKey, ruleVal string, customMsgMap map case "min-length": min, err := strconv.Atoi(ruleVal) if valueLen < min || err != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.Itoa(min), -1) } case "max-length": max, err := strconv.Atoi(ruleVal) if valueLen > max || err != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":max", strconv.Itoa(max), -1) } case "size": size, err := strconv.Atoi(ruleVal) if valueLen != size || err != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":size", strconv.Itoa(size), -1) } } diff --git a/util/gvalid/gvalid_validator_rule_range.go b/util/gvalid/gvalid_validator_rule_range.go index 71627eb53..31c747075 100644 --- a/util/gvalid/gvalid_validator_rule_range.go +++ b/util/gvalid/gvalid_validator_rule_range.go @@ -7,12 +7,13 @@ package gvalid import ( + "context" "strconv" "strings" ) // checkRange checks `value` using range rules. -func (v *Validator) checkRange(value, ruleKey, ruleVal string, customMsgMap map[string]string) string { +func (v *Validator) checkRange(ctx context.Context, value, ruleKey, ruleVal string, customMsgMap map[string]string) string { msg := "" switch ruleKey { // Value range. @@ -32,7 +33,7 @@ func (v *Validator) checkRange(value, ruleKey, ruleVal string, customMsgMap map[ } valueF, err := strconv.ParseFloat(value, 10) if valueF < min || valueF > max || err != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.FormatFloat(min, 'f', -1, 64), -1) msg = strings.Replace(msg, ":max", strconv.FormatFloat(max, 'f', -1, 64), -1) } @@ -44,7 +45,7 @@ func (v *Validator) checkRange(value, ruleKey, ruleVal string, customMsgMap map[ valueN, err2 = strconv.ParseFloat(value, 10) ) if valueN < min || err1 != nil || err2 != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.FormatFloat(min, 'f', -1, 64), -1) } @@ -55,7 +56,7 @@ func (v *Validator) checkRange(value, ruleKey, ruleVal string, customMsgMap map[ valueN, err2 = strconv.ParseFloat(value, 10) ) if valueN > max || err1 != nil || err2 != nil { - msg = v.getErrorMessageByRule(ruleKey, customMsgMap) + msg = v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) msg = strings.Replace(msg, ":max", strconv.FormatFloat(max, 'f', -1, 64), -1) } diff --git a/util/gvalid/gvalid_z_example_test.go b/util/gvalid/gvalid_z_example_test.go index d11fb4e9f..a7d421d95 100644 --- a/util/gvalid/gvalid_z_example_test.go +++ b/util/gvalid/gvalid_z_example_test.go @@ -10,6 +10,7 @@ import ( "context" "errors" "fmt" + "github.com/gogf/gf/os/gctx" "math" "reflect" @@ -30,7 +31,7 @@ func ExampleCheckMap() { "password@required|length:6,16|same:password2#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等", "password2@required|length:6,16#", } - if e := gvalid.CheckMap(context.TODO(), params, rules); e != nil { + if e := gvalid.CheckMap(gctx.New(), params, rules); e != nil { fmt.Println(e.Map()) fmt.Println(e.FirstItem()) fmt.Println(e.FirstString()) @@ -52,7 +53,7 @@ func ExampleCheckMap2() { "password@required|length:6,16|same:password2#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等", "password2@required|length:6,16#", } - if e := gvalid.CheckMap(context.TODO(), params, rules); e != nil { + if e := gvalid.CheckMap(gctx.New(), params, rules); e != nil { fmt.Println(e.Map()) fmt.Println(e.FirstItem()) fmt.Println(e.FirstString()) @@ -74,7 +75,7 @@ func ExampleCheckStruct() { Page: 1, Size: 10, } - err := gvalid.CheckStruct(context.TODO(), obj, nil) + err := gvalid.CheckStruct(gctx.New(), obj, nil) fmt.Println(err == nil) // Output: // true @@ -91,7 +92,7 @@ func ExampleCheckStruct2() { Page: 1, Size: 10, } - err := gvalid.CheckStruct(context.TODO(), obj, nil) + err := gvalid.CheckStruct(gctx.New(), obj, nil) fmt.Println(err == nil) // Output: // true @@ -108,7 +109,7 @@ func ExampleCheckStruct3() { Page: 1, Size: 10, } - err := gvalid.CheckStruct(context.TODO(), obj, nil) + err := gvalid.CheckStruct(gctx.New(), obj, nil) fmt.Println(err) // Output: // project id must between 1, 10000 @@ -141,7 +142,7 @@ func ExampleRegisterRule() { } return nil }) - err := gvalid.CheckStruct(context.TODO(), user, nil) + err := gvalid.CheckStruct(gctx.New(), user, nil) fmt.Println(err.Error()) // May Output: // 用户名称已被占用 @@ -175,14 +176,14 @@ func ExampleRegisterRule_OverwriteRequired() { } return nil }) - fmt.Println(gvalid.CheckValue(context.TODO(), "", "required", "It's required")) - fmt.Println(gvalid.CheckValue(context.TODO(), 0, "required", "It's required")) - fmt.Println(gvalid.CheckValue(context.TODO(), false, "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), "", "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), 0, "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), false, "required", "It's required")) gvalid.DeleteRule(rule) fmt.Println("rule deleted") - fmt.Println(gvalid.CheckValue(context.TODO(), "", "required", "It's required")) - fmt.Println(gvalid.CheckValue(context.TODO(), 0, "required", "It's required")) - fmt.Println(gvalid.CheckValue(context.TODO(), false, "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), "", "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), 0, "required", "It's required")) + fmt.Println(gvalid.CheckValue(gctx.New(), false, "required", "It's required")) // Output: // It's required // It's required @@ -197,7 +198,10 @@ func ExampleValidator_Rules() { data := g.Map{ "password": "123", } - err := g.Validator().Data(data).Rules("required-with:password").Messages("请输入确认密码").CheckValue("") + err := g.Validator().Data(data). + Rules("required-with:password"). + Messages("请输入确认密码"). + CheckValue(gctx.New(), "") fmt.Println(err.String()) // Output: @@ -205,7 +209,9 @@ func ExampleValidator_Rules() { } func ExampleValidator_CheckValue() { - err := g.Validator().Rules("min:18").Messages("未成年人不允许注册哟").CheckValue(16) + err := g.Validator().Rules("min:18"). + Messages("未成年人不允许注册哟"). + CheckValue(gctx.New(), 16) fmt.Println(err.String()) // Output: @@ -230,7 +236,10 @@ func ExampleValidator_CheckMap() { "same": "两次密码输入不相等", }, } - err := g.Validator().Messages(messages).Rules(rules).CheckMap(params) + err := g.Validator(). + Messages(messages). + Rules(rules). + CheckMap(gctx.New(), params) if err != nil { g.Dump(err.Maps()) } @@ -259,7 +268,7 @@ func ExampleValidator_CheckStruct() { if err := gconv.Scan(data, &user); err != nil { panic(err) } - err := g.Validator().Data(data).CheckStruct(user) + err := g.Validator().Data(data).CheckStruct(gctx.New(), user) if err != nil { fmt.Println(err.Items()) } diff --git a/util/gvalid/gvalid_z_unit_basic_all_test.go b/util/gvalid/gvalid_z_unit_basic_all_test.go index 906d768fa..3febb015f 100755 --- a/util/gvalid/gvalid_z_unit_basic_all_test.go +++ b/util/gvalid/gvalid_z_unit_basic_all_test.go @@ -10,6 +10,7 @@ import ( "context" "github.com/gogf/gf/errors/gcode" "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/os/gctx" "github.com/gogf/gf/os/gtime" "testing" "time" @@ -19,6 +20,10 @@ import ( "github.com/gogf/gf/util/gvalid" ) +var ( + ctx = gctx.New() +) + func Test_Check(t *testing.T) { gtest.C(t, func(t *gtest.T) { rule := "abc:6,16" @@ -1018,13 +1023,13 @@ func Test_InternalError_String(t *testing.T) { func Test_Code(t *testing.T) { gtest.C(t, func(t *gtest.T) { - err := g.Validator().Rules("required").CheckValue("") + err := g.Validator().Rules("required").CheckValue(ctx, "") t.AssertNE(err, nil) t.Assert(gerror.Code(err), gcode.CodeValidationFailed) }) gtest.C(t, func(t *gtest.T) { - err := g.Validator().Rules("none-exist-rule").CheckValue("") + err := g.Validator().Rules("none-exist-rule").CheckValue(ctx, "") t.AssertNE(err, nil) t.Assert(gerror.Code(err), gcode.CodeInternalError) }) @@ -1036,7 +1041,7 @@ func Test_Bail(t *testing.T) { err := g.Validator(). Rules("required|min:1|between:1,100"). Messages("|min number is 1|size is between 1 and 100"). - CheckValue(-1) + CheckValue(ctx, -1) t.AssertNE(err, nil) t.Assert(err.Error(), "min number is 1; size is between 1 and 100") }) @@ -1046,7 +1051,7 @@ func Test_Bail(t *testing.T) { err := g.Validator(). Rules("bail|required|min:1|between:1,100"). Messages("||min number is 1|size is between 1 and 100"). - CheckValue(-1) + CheckValue(ctx, -1) t.AssertNE(err, nil) t.Assert(err.Error(), "min number is 1") }) @@ -1061,7 +1066,7 @@ func Test_Bail(t *testing.T) { Page: 1, Size: -1, } - err := g.Validator().CheckStruct(obj) + err := g.Validator().CheckStruct(ctx, obj) t.AssertNE(err, nil) t.Assert(err.Error(), "min number is 1; size is between 1 and 100") }) @@ -1075,7 +1080,7 @@ func Test_Bail(t *testing.T) { Page: 1, Size: -1, } - err := g.Validator().CheckStruct(obj) + err := g.Validator().CheckStruct(ctx, obj) t.AssertNE(err, nil) t.Assert(err.Error(), "min number is 1") }) diff --git a/util/gvalid/gvalid_z_unit_checkmap_test.go b/util/gvalid/gvalid_z_unit_checkmap_test.go index 7750e923b..a25df1b23 100755 --- a/util/gvalid/gvalid_z_unit_checkmap_test.go +++ b/util/gvalid/gvalid_z_unit_checkmap_test.go @@ -225,7 +225,7 @@ func Test_Map_Bail(t *testing.T) { "password@required|length:6,16|same:password2#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等", "password2@required|length:6,16#", } - err := g.Validator().Bail().Rules(rules).CheckMap(params) + err := g.Validator().Bail().Rules(rules).CheckMap(ctx, params) t.AssertNE(err, nil) t.Assert(err.String(), "账号不能为空; 账号长度应当在6到16之间") }) @@ -241,7 +241,7 @@ func Test_Map_Bail(t *testing.T) { "password@required|length:6,16|same:password2#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等", "password2@required|length:6,16#", } - err := g.Validator().Bail().Rules(rules).CheckMap(params) + err := g.Validator().Bail().Rules(rules).CheckMap(ctx, params) t.AssertNE(err, nil) t.Assert(err.String(), "账号不能为空") }) diff --git a/util/gvalid/gvalid_z_unit_custom_rule_test.go b/util/gvalid/gvalid_z_unit_custom_rule_test.go index 0a4e694b4..1ce2e5fac 100644 --- a/util/gvalid/gvalid_z_unit_custom_rule_test.go +++ b/util/gvalid/gvalid_z_unit_custom_rule_test.go @@ -171,14 +171,17 @@ func TestValidator_RuleFunc(t *testing.T) { return nil } gtest.C(t, func(t *gtest.T) { - err := g.Validator().Rules(ruleName).Messages("custom message").RuleFunc(ruleName, ruleFunc).CheckValue("123456") + err := g.Validator().Rules(ruleName). + Messages("custom message"). + RuleFunc(ruleName, ruleFunc). + CheckValue(ctx, "123456") t.Assert(err.String(), "custom message") err = g.Validator(). Rules(ruleName). Messages("custom message"). Data(g.Map{"data": "123456"}). RuleFunc(ruleName, ruleFunc). - CheckValue("123456") + CheckValue(ctx, "123456") t.AssertNil(err) }) // Error with struct validation. @@ -191,7 +194,7 @@ func TestValidator_RuleFunc(t *testing.T) { Value: "123", Data: "123456", } - err := g.Validator().RuleFunc(ruleName, ruleFunc).CheckStruct(st) + err := g.Validator().RuleFunc(ruleName, ruleFunc).CheckStruct(ctx, st) t.Assert(err.String(), "自定义错误") }) // No error with struct validation. @@ -204,7 +207,7 @@ func TestValidator_RuleFunc(t *testing.T) { Value: "123456", Data: "123456", } - err := g.Validator().RuleFunc(ruleName, ruleFunc).CheckStruct(st) + err := g.Validator().RuleFunc(ruleName, ruleFunc).CheckStruct(ctx, st) t.AssertNil(err) }) } @@ -227,7 +230,7 @@ func TestValidator_RuleFuncMap(t *testing.T) { Messages("custom message"). RuleFuncMap(map[string]gvalid.RuleFunc{ ruleName: ruleFunc, - }).CheckValue("123456") + }).CheckValue(ctx, "123456") t.Assert(err.String(), "custom message") err = g.Validator(). Rules(ruleName). @@ -236,7 +239,7 @@ func TestValidator_RuleFuncMap(t *testing.T) { RuleFuncMap(map[string]gvalid.RuleFunc{ ruleName: ruleFunc, }). - CheckValue("123456") + CheckValue(ctx, "123456") t.AssertNil(err) }) // Error with struct validation. @@ -252,7 +255,7 @@ func TestValidator_RuleFuncMap(t *testing.T) { err := g.Validator(). RuleFuncMap(map[string]gvalid.RuleFunc{ ruleName: ruleFunc, - }).CheckStruct(st) + }).CheckStruct(ctx, st) t.Assert(err.String(), "自定义错误") }) // No error with struct validation. @@ -268,7 +271,7 @@ func TestValidator_RuleFuncMap(t *testing.T) { err := g.Validator(). RuleFuncMap(map[string]gvalid.RuleFunc{ ruleName: ruleFunc, - }).CheckStruct(st) + }).CheckStruct(ctx, st) t.AssertNil(err) }) } diff --git a/util/gvalid/gvalid_z_unit_i18n_test.go b/util/gvalid/gvalid_z_unit_i18n_test.go index 5294c7e3c..c7bb6963c 100644 --- a/util/gvalid/gvalid_z_unit_i18n_test.go +++ b/util/gvalid/gvalid_z_unit_i18n_test.go @@ -24,14 +24,14 @@ func TestValidator_I18n(t *testing.T) { validator = gvalid.New().I18n(i18nManager) ) gtest.C(t, func(t *gtest.T) { - err = validator.Rules("required").CheckValue("") + err = validator.Rules("required").CheckValue(ctx, "") t.Assert(err.String(), "The field is required") - err = validator.Ctx(ctxCn).Rules("required").CheckValue("") + err = validator.Rules("required").CheckValue(ctxCn, "") t.Assert(err.String(), "字段不能为空") }) gtest.C(t, func(t *gtest.T) { - err = validator.Ctx(ctxCn).Rules("required").Messages("CustomMessage").CheckValue("") + err = validator.Rules("required").Messages("CustomMessage").CheckValue(ctxCn, "") t.Assert(err.String(), "自定义错误") }) gtest.C(t, func(t *gtest.T) { @@ -44,7 +44,7 @@ func TestValidator_I18n(t *testing.T) { Page: 1, Size: 10, } - err := validator.Ctx(ctxCn).CheckStruct(obj) + err = validator.CheckStruct(ctxCn, obj) t.Assert(err.String(), "项目ID必须大于等于1并且要小于等于10000") }) }