14 // Func accepts a FieldLevel interface for all validation needs. The return
15 // value should be true when validation succeeds.
16 type Func func(fl FieldLevel) bool
18 // FuncCtx accepts a context.Context and FieldLevel interface for all
19 // validation needs. The return value should be true when validation succeeds.
20 type FuncCtx func(ctx context.Context, fl FieldLevel) bool
22 // wrapFunc wraps noramal Func makes it compatible with FuncCtx
23 func wrapFunc(fn Func) FuncCtx {
25 return nil // be sure not to wrap a bad function.
27 return func(ctx context.Context, fl FieldLevel) bool {
33 restrictedTags = map[string]struct{}{
37 skipValidationTag: {},
45 // BakedInAliasValidators is a default mapping of a single validation tag that
46 // defines a common or complex set of validation(s) to simplify
47 // adding validation to structs.
48 bakedInAliases = map[string]string{
49 "iscolor": "hexcolor|rgb|rgba|hsl|hsla",
52 // BakedInValidators is the default map of ValidationFunc
53 // you can add, remove or even replace items to suite your needs,
54 // or even disregard and use your own map if so desired.
55 bakedInValidators = map[string]Func{
57 "isdefault": isDefault,
68 "eqcsfield": isEqCrossStructField,
69 "necsfield": isNeCrossStructField,
70 "gtcsfield": isGtCrossStructField,
71 "gtecsfield": isGteCrossStructField,
72 "ltcsfield": isLtCrossStructField,
73 "ltecsfield": isLteCrossStructField,
75 "gtefield": isGteField,
77 "ltefield": isLteField,
80 "alphanum": isAlphanum,
81 "alphaunicode": isAlphaUnicode,
82 "alphanumunicode": isAlphanumUnicode,
85 "hexadecimal": isHexadecimal,
86 "hexcolor": isHEXColor,
96 "containsany": containsAny,
97 "containsrune": containsRune,
99 "excludesall": excludesAll,
100 "excludesrune": excludesRune,
109 "printascii": isPrintableASCII,
110 "multibyte": hasMultiByteCharacter,
111 "datauri": isDataURI,
112 "latitude": isLatitude,
113 "longitude": isLongitude,
121 "tcp4_addr": isTCP4AddrResolvable,
122 "tcp6_addr": isTCP6AddrResolvable,
123 "tcp_addr": isTCPAddrResolvable,
124 "udp4_addr": isUDP4AddrResolvable,
125 "udp6_addr": isUDP6AddrResolvable,
126 "udp_addr": isUDPAddrResolvable,
127 "ip4_addr": isIP4AddrResolvable,
128 "ip6_addr": isIP6AddrResolvable,
129 "ip_addr": isIPAddrResolvable,
130 "unix_addr": isUnixAddrResolvable,
132 "hostname": isHostname,
138 // isUnique is the validation function for validating if each array|slice element is unique
139 func isUnique(fl FieldLevel) bool {
142 v := reflect.ValueOf(struct{}{})
144 switch field.Kind() {
145 case reflect.Slice, reflect.Array:
146 m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type()))
148 for i := 0; i < field.Len(); i++ {
149 m.SetMapIndex(field.Index(i), v)
151 return field.Len() == m.Len()
153 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
157 // IsMAC is the validation function for validating if the field's value is a valid MAC address.
158 func isMAC(fl FieldLevel) bool {
160 _, err := net.ParseMAC(fl.Field().String())
165 // IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
166 func isCIDRv4(fl FieldLevel) bool {
168 ip, _, err := net.ParseCIDR(fl.Field().String())
170 return err == nil && ip.To4() != nil
173 // IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
174 func isCIDRv6(fl FieldLevel) bool {
176 ip, _, err := net.ParseCIDR(fl.Field().String())
178 return err == nil && ip.To4() == nil
181 // IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
182 func isCIDR(fl FieldLevel) bool {
184 _, _, err := net.ParseCIDR(fl.Field().String())
189 // IsIPv4 is the validation function for validating if a value is a valid v4 IP address.
190 func isIPv4(fl FieldLevel) bool {
192 ip := net.ParseIP(fl.Field().String())
194 return ip != nil && ip.To4() != nil
197 // IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
198 func isIPv6(fl FieldLevel) bool {
200 ip := net.ParseIP(fl.Field().String())
202 return ip != nil && ip.To4() == nil
205 // IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
206 func isIP(fl FieldLevel) bool {
208 ip := net.ParseIP(fl.Field().String())
213 // IsSSN is the validation function for validating if the field's value is a valid SSN.
214 func isSSN(fl FieldLevel) bool {
218 if field.Len() != 11 {
222 return sSNRegex.MatchString(field.String())
225 // IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
226 func isLongitude(fl FieldLevel) bool {
227 return longitudeRegex.MatchString(fl.Field().String())
230 // IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
231 func isLatitude(fl FieldLevel) bool {
232 return latitudeRegex.MatchString(fl.Field().String())
235 // IsDataURI is the validation function for validating if the field's value is a valid data URI.
236 func isDataURI(fl FieldLevel) bool {
238 uri := strings.SplitN(fl.Field().String(), ",", 2)
244 if !dataURIRegex.MatchString(uri[0]) {
248 return base64Regex.MatchString(uri[1])
251 // HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
252 func hasMultiByteCharacter(fl FieldLevel) bool {
256 if field.Len() == 0 {
260 return multibyteRegex.MatchString(field.String())
263 // IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
264 func isPrintableASCII(fl FieldLevel) bool {
265 return printableASCIIRegex.MatchString(fl.Field().String())
268 // IsASCII is the validation function for validating if the field's value is a valid ASCII character.
269 func isASCII(fl FieldLevel) bool {
270 return aSCIIRegex.MatchString(fl.Field().String())
273 // IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
274 func isUUID5(fl FieldLevel) bool {
275 return uUID5Regex.MatchString(fl.Field().String())
278 // IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
279 func isUUID4(fl FieldLevel) bool {
280 return uUID4Regex.MatchString(fl.Field().String())
283 // IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
284 func isUUID3(fl FieldLevel) bool {
285 return uUID3Regex.MatchString(fl.Field().String())
288 // IsUUID is the validation function for validating if the field's value is a valid UUID of any version.
289 func isUUID(fl FieldLevel) bool {
290 return uUIDRegex.MatchString(fl.Field().String())
293 // IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
294 func isISBN(fl FieldLevel) bool {
295 return isISBN10(fl) || isISBN13(fl)
298 // IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
299 func isISBN13(fl FieldLevel) bool {
301 s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 4), " ", "", 4)
303 if !iSBN13Regex.MatchString(s) {
310 factor := []int32{1, 3}
312 for i = 0; i < 12; i++ {
313 checksum += factor[i%2] * int32(s[i]-'0')
316 return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0
319 // IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
320 func isISBN10(fl FieldLevel) bool {
322 s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 3), " ", "", 3)
324 if !iSBN10Regex.MatchString(s) {
331 for i = 0; i < 9; i++ {
332 checksum += (i + 1) * int32(s[i]-'0')
338 checksum += 10 * int32(s[9]-'0')
341 return checksum%11 == 0
344 // ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within the param.
345 func excludesRune(fl FieldLevel) bool {
346 return !containsRune(fl)
349 // ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param.
350 func excludesAll(fl FieldLevel) bool {
351 return !containsAny(fl)
354 // Excludes is the validation function for validating that the field's value does not contain the text specified within the param.
355 func excludes(fl FieldLevel) bool {
359 // ContainsRune is the validation function for validating that the field's value contains the rune specified within the param.
360 func containsRune(fl FieldLevel) bool {
362 r, _ := utf8.DecodeRuneInString(fl.Param())
364 return strings.ContainsRune(fl.Field().String(), r)
367 // ContainsAny is the validation function for validating that the field's value contains any of the characters specified within the param.
368 func containsAny(fl FieldLevel) bool {
369 return strings.ContainsAny(fl.Field().String(), fl.Param())
372 // Contains is the validation function for validating that the field's value contains the text specified within the param.
373 func contains(fl FieldLevel) bool {
374 return strings.Contains(fl.Field().String(), fl.Param())
377 // IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
378 func isNeField(fl FieldLevel) bool {
383 currentField, currentKind, ok := fl.GetStructFieldOK()
385 if !ok || currentKind != kind {
391 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
392 return field.Int() != currentField.Int()
394 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
395 return field.Uint() != currentField.Uint()
397 case reflect.Float32, reflect.Float64:
398 return field.Float() != currentField.Float()
400 case reflect.Slice, reflect.Map, reflect.Array:
401 return int64(field.Len()) != int64(currentField.Len())
405 fieldType := field.Type()
407 // Not Same underlying type i.e. struct and time
408 if fieldType != currentField.Type() {
412 if fieldType == timeType {
414 t := currentField.Interface().(time.Time)
415 fieldTime := field.Interface().(time.Time)
417 return !fieldTime.Equal(t)
422 // default reflect.String:
423 return field.String() != currentField.String()
426 // IsNe is the validation function for validating that the field's value does not equal the provided param value.
427 func isNe(fl FieldLevel) bool {
431 // IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
432 func isLteCrossStructField(fl FieldLevel) bool {
437 topField, topKind, ok := fl.GetStructFieldOK()
438 if !ok || topKind != kind {
444 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
445 return field.Int() <= topField.Int()
447 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
448 return field.Uint() <= topField.Uint()
450 case reflect.Float32, reflect.Float64:
451 return field.Float() <= topField.Float()
453 case reflect.Slice, reflect.Map, reflect.Array:
454 return int64(field.Len()) <= int64(topField.Len())
458 fieldType := field.Type()
460 // Not Same underlying type i.e. struct and time
461 if fieldType != topField.Type() {
465 if fieldType == timeType {
467 fieldTime := field.Interface().(time.Time)
468 topTime := topField.Interface().(time.Time)
470 return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
474 // default reflect.String:
475 return field.String() <= topField.String()
478 // IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
479 // NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
480 func isLtCrossStructField(fl FieldLevel) bool {
485 topField, topKind, ok := fl.GetStructFieldOK()
486 if !ok || topKind != kind {
492 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
493 return field.Int() < topField.Int()
495 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
496 return field.Uint() < topField.Uint()
498 case reflect.Float32, reflect.Float64:
499 return field.Float() < topField.Float()
501 case reflect.Slice, reflect.Map, reflect.Array:
502 return int64(field.Len()) < int64(topField.Len())
506 fieldType := field.Type()
508 // Not Same underlying type i.e. struct and time
509 if fieldType != topField.Type() {
513 if fieldType == timeType {
515 fieldTime := field.Interface().(time.Time)
516 topTime := topField.Interface().(time.Time)
518 return fieldTime.Before(topTime)
522 // default reflect.String:
523 return field.String() < topField.String()
526 // IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
527 func isGteCrossStructField(fl FieldLevel) bool {
532 topField, topKind, ok := fl.GetStructFieldOK()
533 if !ok || topKind != kind {
539 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
540 return field.Int() >= topField.Int()
542 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
543 return field.Uint() >= topField.Uint()
545 case reflect.Float32, reflect.Float64:
546 return field.Float() >= topField.Float()
548 case reflect.Slice, reflect.Map, reflect.Array:
549 return int64(field.Len()) >= int64(topField.Len())
553 fieldType := field.Type()
555 // Not Same underlying type i.e. struct and time
556 if fieldType != topField.Type() {
560 if fieldType == timeType {
562 fieldTime := field.Interface().(time.Time)
563 topTime := topField.Interface().(time.Time)
565 return fieldTime.After(topTime) || fieldTime.Equal(topTime)
569 // default reflect.String:
570 return field.String() >= topField.String()
573 // IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
574 func isGtCrossStructField(fl FieldLevel) bool {
579 topField, topKind, ok := fl.GetStructFieldOK()
580 if !ok || topKind != kind {
586 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
587 return field.Int() > topField.Int()
589 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
590 return field.Uint() > topField.Uint()
592 case reflect.Float32, reflect.Float64:
593 return field.Float() > topField.Float()
595 case reflect.Slice, reflect.Map, reflect.Array:
596 return int64(field.Len()) > int64(topField.Len())
600 fieldType := field.Type()
602 // Not Same underlying type i.e. struct and time
603 if fieldType != topField.Type() {
607 if fieldType == timeType {
609 fieldTime := field.Interface().(time.Time)
610 topTime := topField.Interface().(time.Time)
612 return fieldTime.After(topTime)
616 // default reflect.String:
617 return field.String() > topField.String()
620 // IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
621 func isNeCrossStructField(fl FieldLevel) bool {
626 topField, currentKind, ok := fl.GetStructFieldOK()
627 if !ok || currentKind != kind {
633 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
634 return topField.Int() != field.Int()
636 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
637 return topField.Uint() != field.Uint()
639 case reflect.Float32, reflect.Float64:
640 return topField.Float() != field.Float()
642 case reflect.Slice, reflect.Map, reflect.Array:
643 return int64(topField.Len()) != int64(field.Len())
647 fieldType := field.Type()
649 // Not Same underlying type i.e. struct and time
650 if fieldType != topField.Type() {
654 if fieldType == timeType {
656 t := field.Interface().(time.Time)
657 fieldTime := topField.Interface().(time.Time)
659 return !fieldTime.Equal(t)
663 // default reflect.String:
664 return topField.String() != field.String()
667 // IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
668 func isEqCrossStructField(fl FieldLevel) bool {
673 topField, topKind, ok := fl.GetStructFieldOK()
674 if !ok || topKind != kind {
680 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
681 return topField.Int() == field.Int()
683 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
684 return topField.Uint() == field.Uint()
686 case reflect.Float32, reflect.Float64:
687 return topField.Float() == field.Float()
689 case reflect.Slice, reflect.Map, reflect.Array:
690 return int64(topField.Len()) == int64(field.Len())
694 fieldType := field.Type()
696 // Not Same underlying type i.e. struct and time
697 if fieldType != topField.Type() {
701 if fieldType == timeType {
703 t := field.Interface().(time.Time)
704 fieldTime := topField.Interface().(time.Time)
706 return fieldTime.Equal(t)
710 // default reflect.String:
711 return topField.String() == field.String()
714 // IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
715 func isEqField(fl FieldLevel) bool {
720 currentField, currentKind, ok := fl.GetStructFieldOK()
721 if !ok || currentKind != kind {
727 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
728 return field.Int() == currentField.Int()
730 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
731 return field.Uint() == currentField.Uint()
733 case reflect.Float32, reflect.Float64:
734 return field.Float() == currentField.Float()
736 case reflect.Slice, reflect.Map, reflect.Array:
737 return int64(field.Len()) == int64(currentField.Len())
741 fieldType := field.Type()
743 // Not Same underlying type i.e. struct and time
744 if fieldType != currentField.Type() {
748 if fieldType == timeType {
750 t := currentField.Interface().(time.Time)
751 fieldTime := field.Interface().(time.Time)
753 return fieldTime.Equal(t)
758 // default reflect.String:
759 return field.String() == currentField.String()
762 // IsEq is the validation function for validating if the current field's value is equal to the param's value.
763 func isEq(fl FieldLevel) bool {
768 switch field.Kind() {
771 return field.String() == param
773 case reflect.Slice, reflect.Map, reflect.Array:
776 return int64(field.Len()) == p
778 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
781 return field.Int() == p
783 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
786 return field.Uint() == p
788 case reflect.Float32, reflect.Float64:
791 return field.Float() == p
794 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
797 // IsBase64 is the validation function for validating if the current field's value is a valid base 64.
798 func isBase64(fl FieldLevel) bool {
799 return base64Regex.MatchString(fl.Field().String())
802 // IsURI is the validation function for validating if the current field's value is a valid URI.
803 func isURI(fl FieldLevel) bool {
807 switch field.Kind() {
813 // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
814 // emulate browser and strip the '#' suffix prior to validation. see issue-#237
815 if i := strings.Index(s, "#"); i > -1 {
823 _, err := url.ParseRequestURI(s)
828 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
831 // IsURL is the validation function for validating if the current field's value is a valid URL.
832 func isURL(fl FieldLevel) bool {
836 switch field.Kind() {
843 // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
844 // emulate browser and strip the '#' suffix prior to validation. see issue-#237
845 if i = strings.Index(s, "#"); i > -1 {
853 url, err := url.ParseRequestURI(s)
855 if err != nil || url.Scheme == "" {
862 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
865 // IsEmail is the validation function for validating if the current field's value is a valid email address.
866 func isEmail(fl FieldLevel) bool {
867 return emailRegex.MatchString(fl.Field().String())
870 // IsHSLA is the validation function for validating if the current field's value is a valid HSLA color.
871 func isHSLA(fl FieldLevel) bool {
872 return hslaRegex.MatchString(fl.Field().String())
875 // IsHSL is the validation function for validating if the current field's value is a valid HSL color.
876 func isHSL(fl FieldLevel) bool {
877 return hslRegex.MatchString(fl.Field().String())
880 // IsRGBA is the validation function for validating if the current field's value is a valid RGBA color.
881 func isRGBA(fl FieldLevel) bool {
882 return rgbaRegex.MatchString(fl.Field().String())
885 // IsRGB is the validation function for validating if the current field's value is a valid RGB color.
886 func isRGB(fl FieldLevel) bool {
887 return rgbRegex.MatchString(fl.Field().String())
890 // IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
891 func isHEXColor(fl FieldLevel) bool {
892 return hexcolorRegex.MatchString(fl.Field().String())
895 // IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
896 func isHexadecimal(fl FieldLevel) bool {
897 return hexadecimalRegex.MatchString(fl.Field().String())
900 // IsNumber is the validation function for validating if the current field's value is a valid number.
901 func isNumber(fl FieldLevel) bool {
902 return numberRegex.MatchString(fl.Field().String())
905 // IsNumeric is the validation function for validating if the current field's value is a valid numeric value.
906 func isNumeric(fl FieldLevel) bool {
907 return numericRegex.MatchString(fl.Field().String())
910 // IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
911 func isAlphanum(fl FieldLevel) bool {
912 return alphaNumericRegex.MatchString(fl.Field().String())
915 // IsAlpha is the validation function for validating if the current field's value is a valid alpha value.
916 func isAlpha(fl FieldLevel) bool {
917 return alphaRegex.MatchString(fl.Field().String())
920 // IsAlphanumUnicode is the validation function for validating if the current field's value is a valid alphanumeric unicode value.
921 func isAlphanumUnicode(fl FieldLevel) bool {
922 return alphaUnicodeNumericRegex.MatchString(fl.Field().String())
925 // IsAlphaUnicode is the validation function for validating if the current field's value is a valid alpha unicode value.
926 func isAlphaUnicode(fl FieldLevel) bool {
927 return alphaUnicodeRegex.MatchString(fl.Field().String())
930 // isDefault is the opposite of required aka hasValue
931 func isDefault(fl FieldLevel) bool {
935 // HasValue is the validation function for validating if the current field's value is not the default static value.
936 func hasValue(fl FieldLevel) bool {
940 switch field.Kind() {
941 case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
942 return !field.IsNil()
945 if fl.(*validate).fldIsPointer && field.Interface() != nil {
949 return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface()
953 // IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
954 func isGteField(fl FieldLevel) bool {
959 currentField, currentKind, ok := fl.GetStructFieldOK()
960 if !ok || currentKind != kind {
966 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
968 return field.Int() >= currentField.Int()
970 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
972 return field.Uint() >= currentField.Uint()
974 case reflect.Float32, reflect.Float64:
976 return field.Float() >= currentField.Float()
980 fieldType := field.Type()
982 // Not Same underlying type i.e. struct and time
983 if fieldType != currentField.Type() {
987 if fieldType == timeType {
989 t := currentField.Interface().(time.Time)
990 fieldTime := field.Interface().(time.Time)
992 return fieldTime.After(t) || fieldTime.Equal(t)
996 // default reflect.String
997 return len(field.String()) >= len(currentField.String())
1000 // IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
1001 func isGtField(fl FieldLevel) bool {
1004 kind := field.Kind()
1006 currentField, currentKind, ok := fl.GetStructFieldOK()
1007 if !ok || currentKind != kind {
1013 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1015 return field.Int() > currentField.Int()
1017 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1019 return field.Uint() > currentField.Uint()
1021 case reflect.Float32, reflect.Float64:
1023 return field.Float() > currentField.Float()
1025 case reflect.Struct:
1027 fieldType := field.Type()
1029 // Not Same underlying type i.e. struct and time
1030 if fieldType != currentField.Type() {
1034 if fieldType == timeType {
1036 t := currentField.Interface().(time.Time)
1037 fieldTime := field.Interface().(time.Time)
1039 return fieldTime.After(t)
1043 // default reflect.String
1044 return len(field.String()) > len(currentField.String())
1047 // IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
1048 func isGte(fl FieldLevel) bool {
1053 switch field.Kind() {
1055 case reflect.String:
1058 return int64(utf8.RuneCountInString(field.String())) >= p
1060 case reflect.Slice, reflect.Map, reflect.Array:
1063 return int64(field.Len()) >= p
1065 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1068 return field.Int() >= p
1070 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1073 return field.Uint() >= p
1075 case reflect.Float32, reflect.Float64:
1078 return field.Float() >= p
1080 case reflect.Struct:
1082 if field.Type() == timeType {
1084 now := time.Now().UTC()
1085 t := field.Interface().(time.Time)
1087 return t.After(now) || t.Equal(now)
1091 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1094 // IsGt is the validation function for validating if the current field's value is greater than the param's value.
1095 func isGt(fl FieldLevel) bool {
1100 switch field.Kind() {
1102 case reflect.String:
1105 return int64(utf8.RuneCountInString(field.String())) > p
1107 case reflect.Slice, reflect.Map, reflect.Array:
1110 return int64(field.Len()) > p
1112 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1115 return field.Int() > p
1117 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1120 return field.Uint() > p
1122 case reflect.Float32, reflect.Float64:
1125 return field.Float() > p
1126 case reflect.Struct:
1128 if field.Type() == timeType {
1130 return field.Interface().(time.Time).After(time.Now().UTC())
1134 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1137 // HasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
1138 func hasLengthOf(fl FieldLevel) bool {
1143 switch field.Kind() {
1145 case reflect.String:
1148 return int64(utf8.RuneCountInString(field.String())) == p
1150 case reflect.Slice, reflect.Map, reflect.Array:
1153 return int64(field.Len()) == p
1155 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1158 return field.Int() == p
1160 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1163 return field.Uint() == p
1165 case reflect.Float32, reflect.Float64:
1168 return field.Float() == p
1171 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1174 // HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
1175 func hasMinOf(fl FieldLevel) bool {
1179 // IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
1180 func isLteField(fl FieldLevel) bool {
1183 kind := field.Kind()
1185 currentField, currentKind, ok := fl.GetStructFieldOK()
1186 if !ok || currentKind != kind {
1192 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1194 return field.Int() <= currentField.Int()
1196 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1198 return field.Uint() <= currentField.Uint()
1200 case reflect.Float32, reflect.Float64:
1202 return field.Float() <= currentField.Float()
1204 case reflect.Struct:
1206 fieldType := field.Type()
1208 // Not Same underlying type i.e. struct and time
1209 if fieldType != currentField.Type() {
1213 if fieldType == timeType {
1215 t := currentField.Interface().(time.Time)
1216 fieldTime := field.Interface().(time.Time)
1218 return fieldTime.Before(t) || fieldTime.Equal(t)
1222 // default reflect.String
1223 return len(field.String()) <= len(currentField.String())
1226 // IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
1227 func isLtField(fl FieldLevel) bool {
1230 kind := field.Kind()
1232 currentField, currentKind, ok := fl.GetStructFieldOK()
1233 if !ok || currentKind != kind {
1239 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1241 return field.Int() < currentField.Int()
1243 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1245 return field.Uint() < currentField.Uint()
1247 case reflect.Float32, reflect.Float64:
1249 return field.Float() < currentField.Float()
1251 case reflect.Struct:
1253 fieldType := field.Type()
1255 // Not Same underlying type i.e. struct and time
1256 if fieldType != currentField.Type() {
1260 if fieldType == timeType {
1262 t := currentField.Interface().(time.Time)
1263 fieldTime := field.Interface().(time.Time)
1265 return fieldTime.Before(t)
1269 // default reflect.String
1270 return len(field.String()) < len(currentField.String())
1273 // IsLte is the validation function for validating if the current field's value is less than or equal to the param's value.
1274 func isLte(fl FieldLevel) bool {
1279 switch field.Kind() {
1281 case reflect.String:
1284 return int64(utf8.RuneCountInString(field.String())) <= p
1286 case reflect.Slice, reflect.Map, reflect.Array:
1289 return int64(field.Len()) <= p
1291 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1294 return field.Int() <= p
1296 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1299 return field.Uint() <= p
1301 case reflect.Float32, reflect.Float64:
1304 return field.Float() <= p
1306 case reflect.Struct:
1308 if field.Type() == timeType {
1310 now := time.Now().UTC()
1311 t := field.Interface().(time.Time)
1313 return t.Before(now) || t.Equal(now)
1317 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1320 // IsLt is the validation function for validating if the current field's value is less than the param's value.
1321 func isLt(fl FieldLevel) bool {
1326 switch field.Kind() {
1328 case reflect.String:
1331 return int64(utf8.RuneCountInString(field.String())) < p
1333 case reflect.Slice, reflect.Map, reflect.Array:
1336 return int64(field.Len()) < p
1338 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1341 return field.Int() < p
1343 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1346 return field.Uint() < p
1348 case reflect.Float32, reflect.Float64:
1351 return field.Float() < p
1353 case reflect.Struct:
1355 if field.Type() == timeType {
1357 return field.Interface().(time.Time).Before(time.Now().UTC())
1361 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1364 // HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
1365 func hasMaxOf(fl FieldLevel) bool {
1369 // IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
1370 func isTCP4AddrResolvable(fl FieldLevel) bool {
1376 _, err := net.ResolveTCPAddr("tcp4", fl.Field().String())
1380 // IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
1381 func isTCP6AddrResolvable(fl FieldLevel) bool {
1387 _, err := net.ResolveTCPAddr("tcp6", fl.Field().String())
1392 // IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
1393 func isTCPAddrResolvable(fl FieldLevel) bool {
1395 if !isIP4Addr(fl) && !isIP6Addr(fl) {
1399 _, err := net.ResolveTCPAddr("tcp", fl.Field().String())
1404 // IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
1405 func isUDP4AddrResolvable(fl FieldLevel) bool {
1411 _, err := net.ResolveUDPAddr("udp4", fl.Field().String())
1416 // IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
1417 func isUDP6AddrResolvable(fl FieldLevel) bool {
1423 _, err := net.ResolveUDPAddr("udp6", fl.Field().String())
1428 // IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
1429 func isUDPAddrResolvable(fl FieldLevel) bool {
1431 if !isIP4Addr(fl) && !isIP6Addr(fl) {
1435 _, err := net.ResolveUDPAddr("udp", fl.Field().String())
1440 // IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
1441 func isIP4AddrResolvable(fl FieldLevel) bool {
1447 _, err := net.ResolveIPAddr("ip4", fl.Field().String())
1452 // IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
1453 func isIP6AddrResolvable(fl FieldLevel) bool {
1459 _, err := net.ResolveIPAddr("ip6", fl.Field().String())
1464 // IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
1465 func isIPAddrResolvable(fl FieldLevel) bool {
1471 _, err := net.ResolveIPAddr("ip", fl.Field().String())
1476 // IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
1477 func isUnixAddrResolvable(fl FieldLevel) bool {
1479 _, err := net.ResolveUnixAddr("unix", fl.Field().String())
1484 func isIP4Addr(fl FieldLevel) bool {
1486 val := fl.Field().String()
1488 if idx := strings.LastIndex(val, ":"); idx != -1 {
1492 ip := net.ParseIP(val)
1494 return ip != nil && ip.To4() != nil
1497 func isIP6Addr(fl FieldLevel) bool {
1499 val := fl.Field().String()
1501 if idx := strings.LastIndex(val, ":"); idx != -1 {
1502 if idx != 0 && val[idx-1:idx] == "]" {
1503 val = val[1 : idx-1]
1507 ip := net.ParseIP(val)
1509 return ip != nil && ip.To4() == nil
1512 func isHostname(fl FieldLevel) bool {
1513 return hostnameRegex.MatchString(fl.Field().String())
1516 func isFQDN(fl FieldLevel) bool {
1517 val := fl.Field().String()
1523 if val[len(val)-1] == '.' {
1524 val = val[0 : len(val)-1]
1527 return (strings.IndexAny(val, ".") > -1) &&
1528 hostnameRegex.MatchString(val)