Repository: go-playground/validator
Pull request #759 (2021-04-25 17:59:43)

Postcode validator for value and field
## Rules for postcode validation
- `postcode_iso3166_alpha2`: Use directly with a value of country code in ISO 3316 alpha 2
- `postcode_iso3166_alpha2_field`: Use directly with a field which should contain a value of country code in ISO 3316 alpha 2

## Notes
- Original discussion https://github.com/go-playground/validator/discussions/751
- It does not support ISO 3316 other types, and not for all countries.
- Added postcode regex for Vietnam (VN) country

**Make sure that you've checked the boxes below before you submit PR:**
- [x] Tests exist or have been written that cover this particular change.

@go-playground/admins

deankarn: Thanks for the PR @vuon9 I'll try and get to it soon. Apologies it might take a while.
coveralls: 
[![Coverage Status](https://coveralls.io/builds/39413073/badge)](https://coveralls.io/builds/39413073)

Coverage decreased (-0.04%) to 76.058% when pulling **3ccc659e6d2cd691f82fff3c03751f396244aab1 on vuon9:postcode-validator** into **b926bf0df97108effd04f9325365cd7969935e16 on go-playground:master**.


Patch:
diff --git a/baked_in.go b/baked_in.go
index 2cc914f..70376ca 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -68,129 +68,131 @@ var (
 	// you can add, remove or even replace items to suite your needs,
 	// or even disregard and use your own map if so desired.
 	bakedInValidators = map[string]Func{
-		"required":                hasValue,
-		"required_if":             requiredIf,
-		"required_unless":         requiredUnless,
-		"required_with":           requiredWith,
-		"required_with_all":       requiredWithAll,
-		"required_without":        requiredWithout,
-		"required_without_all":    requiredWithoutAll,
-		"excluded_with":           excludedWith,
-		"excluded_with_all":       excludedWithAll,
-		"excluded_without":        excludedWithout,
-		"excluded_without_all":    excludedWithoutAll,
-		"isdefault":               isDefault,
-		"len":                     hasLengthOf,
-		"min":                     hasMinOf,
-		"max":                     hasMaxOf,
-		"eq":                      isEq,
-		"ne":                      isNe,
-		"lt":                      isLt,
-		"lte":                     isLte,
-		"gt":                      isGt,
-		"gte":                     isGte,
-		"eqfield":                 isEqField,
-		"eqcsfield":               isEqCrossStructField,
-		"necsfield":               isNeCrossStructField,
-		"gtcsfield":               isGtCrossStructField,
-		"gtecsfield":              isGteCrossStructField,
-		"ltcsfield":               isLtCrossStructField,
-		"ltecsfield":              isLteCrossStructField,
-		"nefield":                 isNeField,
-		"gtefield":                isGteField,
-		"gtfield":                 isGtField,
-		"ltefield":                isLteField,
-		"ltfield":                 isLtField,
-		"fieldcontains":           fieldContains,
-		"fieldexcludes":           fieldExcludes,
-		"alpha":                   isAlpha,
-		"alphanum":                isAlphanum,
-		"alphaunicode":            isAlphaUnicode,
-		"alphanumunicode":         isAlphanumUnicode,
-		"numeric":                 isNumeric,
-		"number":                  isNumber,
-		"hexadecimal":             isHexadecimal,
-		"hexcolor":                isHEXColor,
-		"rgb":                     isRGB,
-		"rgba":                    isRGBA,
-		"hsl":                     isHSL,
-		"hsla":                    isHSLA,
-		"e164":                    isE164,
-		"email":                   isEmail,
-		"url":                     isURL,
-		"uri":                     isURI,
-		"urn_rfc2141":             isUrnRFC2141, // RFC 2141
-		"file":                    isFile,
-		"base64":                  isBase64,
-		"base64url":               isBase64URL,
-		"contains":                contains,
-		"containsany":             containsAny,
-		"containsrune":            containsRune,
-		"excludes":                excludes,
-		"excludesall":             excludesAll,
-		"excludesrune":            excludesRune,
-		"startswith":              startsWith,
-		"endswith":                endsWith,
-		"startsnotwith":           startsNotWith,
-		"endsnotwith":             endsNotWith,
-		"isbn":                    isISBN,
-		"isbn10":                  isISBN10,
-		"isbn13":                  isISBN13,
-		"eth_addr":                isEthereumAddress,
-		"btc_addr":                isBitcoinAddress,
-		"btc_addr_bech32":         isBitcoinBech32Address,
-		"uuid":                    isUUID,
-		"uuid3":                   isUUID3,
-		"uuid4":                   isUUID4,
-		"uuid5":                   isUUID5,
-		"uuid_rfc4122":            isUUIDRFC4122,
-		"uuid3_rfc4122":           isUUID3RFC4122,
-		"uuid4_rfc4122":           isUUID4RFC4122,
-		"uuid5_rfc4122":           isUUID5RFC4122,
-		"ascii":                   isASCII,
-		"printascii":              isPrintableASCII,
-		"multibyte":               hasMultiByteCharacter,
-		"datauri":                 isDataURI,
-		"latitude":                isLatitude,
-		"longitude":               isLongitude,
-		"ssn":                     isSSN,
-		"ipv4":                    isIPv4,
-		"ipv6":                    isIPv6,
-		"ip":                      isIP,
-		"cidrv4":                  isCIDRv4,
-		"cidrv6":                  isCIDRv6,
-		"cidr":                    isCIDR,
-		"tcp4_addr":               isTCP4AddrResolvable,
-		"tcp6_addr":               isTCP6AddrResolvable,
-		"tcp_addr":                isTCPAddrResolvable,
-		"udp4_addr":               isUDP4AddrResolvable,
-		"udp6_addr":               isUDP6AddrResolvable,
-		"udp_addr":                isUDPAddrResolvable,
-		"ip4_addr":                isIP4AddrResolvable,
-		"ip6_addr":                isIP6AddrResolvable,
-		"ip_addr":                 isIPAddrResolvable,
-		"unix_addr":               isUnixAddrResolvable,
-		"mac":                     isMAC,
-		"hostname":                isHostnameRFC952,  // RFC 952
-		"hostname_rfc1123":        isHostnameRFC1123, // RFC 1123
-		"fqdn":                    isFQDN,
-		"unique":                  isUnique,
-		"oneof":                   isOneOf,
-		"html":                    isHTML,
-		"html_encoded":            isHTMLEncoded,
-		"url_encoded":             isURLEncoded,
-		"dir":                     isDir,
-		"json":                    isJSON,
-		"hostname_port":           isHostnamePort,
-		"lowercase":               isLowercase,
-		"uppercase":               isUppercase,
-		"datetime":                isDatetime,
-		"timezone":                isTimeZone,
-		"iso3166_1_alpha2":        isIso3166Alpha2,
-		"iso3166_1_alpha3":        isIso3166Alpha3,
-		"iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
-		"bcp47_language_tag":      isBCP47LanguageTag,
-		"bic":                     isIsoBicFormat,
+		"required":                      hasValue,
+		"required_if":                   requiredIf,
+		"required_unless":               requiredUnless,
+		"required_with":                 requiredWith,
+		"required_with_all":             requiredWithAll,
+		"required_without":              requiredWithout,
+		"required_without_all":          requiredWithoutAll,
+		"excluded_with":                 excludedWith,
+		"excluded_with_all":             excludedWithAll,
+		"excluded_without":              excludedWithout,
+		"excluded_without_all":          excludedWithoutAll,
+		"isdefault":                     isDefault,
+		"len":                           hasLengthOf,
+		"min":                           hasMinOf,
+		"max":                           hasMaxOf,
+		"eq":                            isEq,
+		"ne":                            isNe,
+		"lt":                            isLt,
+		"lte":                           isLte,
+		"gt":                            isGt,
+		"gte":                           isGte,
+		"eqfield":                       isEqField,
+		"eqcsfield":                     isEqCrossStructField,
+		"necsfield":                     isNeCrossStructField,
+		"gtcsfield":                     isGtCrossStructField,
+		"gtecsfield":                    isGteCrossStructField,
+		"ltcsfield":                     isLtCrossStructField,
+		"ltecsfield":                    isLteCrossStructField,
+		"nefield":                       isNeField,
+		"gtefield":                      isGteField,
+		"gtfield":                       isGtField,
+		"ltefield":                      isLteField,
+		"ltfield":                       isLtField,
+		"fieldcontains":                 fieldContains,
+		"fieldexcludes":                 fieldExcludes,
+		"alpha":                         isAlpha,
+		"alphanum":                      isAlphanum,
+		"alphaunicode":                  isAlphaUnicode,
+		"alphanumunicode":               isAlphanumUnicode,
+		"numeric":                       isNumeric,
+		"number":                        isNumber,
+		"hexadecimal":                   isHexadecimal,
+		"hexcolor":                      isHEXColor,
+		"rgb":                           isRGB,
+		"rgba":                          isRGBA,
+		"hsl":                           isHSL,
+		"hsla":                          isHSLA,
+		"e164":                          isE164,
+		"email":                         isEmail,
+		"url":                           isURL,
+		"uri":                           isURI,
+		"urn_rfc2141":                   isUrnRFC2141, // RFC 2141
+		"file":                          isFile,
+		"base64":                        isBase64,
+		"base64url":                     isBase64URL,
+		"contains":                      contains,
+		"containsany":                   containsAny,
+		"containsrune":                  containsRune,
+		"excludes":                      excludes,
+		"excludesall":                   excludesAll,
+		"excludesrune":                  excludesRune,
+		"startswith":                    startsWith,
+		"endswith":                      endsWith,
+		"startsnotwith":                 startsNotWith,
+		"endsnotwith":                   endsNotWith,
+		"isbn":                          isISBN,
+		"isbn10":                        isISBN10,
+		"isbn13":                        isISBN13,
+		"eth_addr":                      isEthereumAddress,
+		"btc_addr":                      isBitcoinAddress,
+		"btc_addr_bech32":               isBitcoinBech32Address,
+		"uuid":                          isUUID,
+		"uuid3":                         isUUID3,
+		"uuid4":                         isUUID4,
+		"uuid5":                         isUUID5,
+		"uuid_rfc4122":                  isUUIDRFC4122,
+		"uuid3_rfc4122":                 isUUID3RFC4122,
+		"uuid4_rfc4122":                 isUUID4RFC4122,
+		"uuid5_rfc4122":                 isUUID5RFC4122,
+		"ascii":                         isASCII,
+		"printascii":                    isPrintableASCII,
+		"multibyte":                     hasMultiByteCharacter,
+		"datauri":                       isDataURI,
+		"latitude":                      isLatitude,
+		"longitude":                     isLongitude,
+		"ssn":                           isSSN,
+		"ipv4":                          isIPv4,
+		"ipv6":                          isIPv6,
+		"ip":                            isIP,
+		"cidrv4":                        isCIDRv4,
+		"cidrv6":                        isCIDRv6,
+		"cidr":                          isCIDR,
+		"tcp4_addr":                     isTCP4AddrResolvable,
+		"tcp6_addr":                     isTCP6AddrResolvable,
+		"tcp_addr":                      isTCPAddrResolvable,
+		"udp4_addr":                     isUDP4AddrResolvable,
+		"udp6_addr":                     isUDP6AddrResolvable,
+		"udp_addr":                      isUDPAddrResolvable,
+		"ip4_addr":                      isIP4AddrResolvable,
+		"ip6_addr":                      isIP6AddrResolvable,
+		"ip_addr":                       isIPAddrResolvable,
+		"unix_addr":                     isUnixAddrResolvable,
+		"mac":                           isMAC,
+		"hostname":                      isHostnameRFC952,  // RFC 952
+		"hostname_rfc1123":              isHostnameRFC1123, // RFC 1123
+		"fqdn":                          isFQDN,
+		"unique":                        isUnique,
+		"oneof":                         isOneOf,
+		"html":                          isHTML,
+		"html_encoded":                  isHTMLEncoded,
+		"url_encoded":                   isURLEncoded,
+		"dir":                           isDir,
+		"json":                          isJSON,
+		"hostname_port":                 isHostnamePort,
+		"lowercase":                     isLowercase,
+		"uppercase":                     isUppercase,
+		"datetime":                      isDatetime,
+		"timezone":                      isTimeZone,
+		"iso3166_1_alpha2":              isIso3166Alpha2,
+		"iso3166_1_alpha3":              isIso3166Alpha3,
+		"iso3166_1_alpha_numeric":       isIso3166AlphaNumeric,
+		"bcp47_language_tag":            isBCP47LanguageTag,
+		"postcode_iso3166_alpha2":       isPostcodeByIso3166Alpha2,
+		"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
+    "bic":                           isIsoBicFormat,
 	}
 )
 
@@ -1205,6 +1207,49 @@ func isEq(fl FieldLevel) bool {
 	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
 }
 
+// isPostcodeByIso3166Alpha2 validates by value which is country code in iso 3166 alpha 2
+// example: `postcode_iso3166_alpha2=US`
+func isPostcodeByIso3166Alpha2(fl FieldLevel) bool {
+	field := fl.Field()
+	param := fl.Param()
+
+	reg, found := postCodeRegexDict[param]
+	if !found {
+		return false
+	}
+
+	return reg.MatchString(field.String())
+}
+
+// isPostcodeByIso3166Alpha2 validates by field which represents for a value of country code in iso 3166 alpha 2
+// example: `postcode_iso3166_alpha2_field=CountryCode`
+func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
+	field := fl.Field()
+	kind := field.Kind()
+
+	params := parseOneOfParam2(fl.Param())
+
+	if len(params) != 1 {
+		return false
+	}
+
+	currentField, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), params[0])
+	if !found {
+		return false
+	}
+
+	if kind != reflect.String {
+		panic(fmt.Sprintf("Bad field type %T", currentField.Interface()))
+	}
+
+	reg, found := postCodeRegexDict[currentField.String()]
+	if !found {
+		return false
+	}
+
+	return reg.MatchString(field.String())
+}
+
 // IsBase64 is the validation function for validating if the current field's value is a valid base 64.
 func isBase64(fl FieldLevel) bool {
 	return base64Regex.MatchString(fl.Field().String())
diff --git a/postcode_regexes.go b/postcode_regexes.go
new file mode 100644
index 0000000..e7e7b68
--- /dev/null
+++ b/postcode_regexes.go
@@ -0,0 +1,173 @@
+package validator
+
+import "regexp"
+
+var postCodePatternDict = map[string]string{
+	"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`,
+	"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
+	"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
+	"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
+	"US": `^\d{5}([ \-]\d{4})?$`,
+	"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`,
+	"DE": `^\d{5}$`,
+	"JP": `^\d{3}-\d{4}$`,
+	"FR": `^\d{2}[ ]?\d{3}$`,
+	"AU": `^\d{4}$`,
+	"IT": `^\d{5}$`,
+	"CH": `^\d{4}$`,
+	"AT": `^\d{4}$`,
+	"ES": `^\d{5}$`,
+	"NL": `^\d{4}[ ]?[A-Z]{2}$`,
+	"BE": `^\d{4}$`,
+	"DK": `^\d{4}$`,
+	"SE": `^\d{3}[ ]?\d{2}$`,
+	"NO": `^\d{4}$`,
+	"BR": `^\d{5}[\-]?\d{3}$`,
+	"PT": `^\d{4}([\-]\d{3})?$`,
+	"FI": `^\d{5}$`,
+	"AX": `^22\d{3}$`,
+	"KR": `^\d{3}[\-]\d{3}$`,
+	"CN": `^\d{6}$`,
+	"TW": `^\d{3}(\d{2})?$`,
+	"SG": `^\d{6}$`,
+	"DZ": `^\d{5}$`,
+	"AD": `^AD\d{3}$`,
+	"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`,
+	"AM": `^(37)?\d{4}$`,
+	"AZ": `^\d{4}$`,
+	"BH": `^((1[0-2]|[2-9])\d{2})?$`,
+	"BD": `^\d{4}$`,
+	"BB": `^(BB\d{5})?$`,
+	"BY": `^\d{6}$`,
+	"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`,
+	"BA": `^\d{5}$`,
+	"IO": `^BBND 1ZZ$`,
+	"BN": `^[A-Z]{2}[ ]?\d{4}$`,
+	"BG": `^\d{4}$`,
+	"KH": `^\d{5}$`,
+	"CV": `^\d{4}$`,
+	"CL": `^\d{7}$`,
+	"CR": `^\d{4,5}|\d{3}-\d{4}$`,
+	"HR": `^\d{5}$`,
+	"CY": `^\d{4}$`,
+	"CZ": `^\d{3}[ ]?\d{2}$`,
+	"DO": `^\d{5}$`,
+	"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`,
+	"EG": `^\d{5}$`,
+	"EE": `^\d{5}$`,
+	"FO": `^\d{3}$`,
+	"GE": `^\d{4}$`,
+	"GR": `^\d{3}[ ]?\d{2}$`,
+	"GL": `^39\d{2}$`,
+	"GT": `^\d{5}$`,
+	"HT": `^\d{4}$`,
+	"HN": `^(?:\d{5})?$`,
+	"HU": `^\d{4}$`,
+	"IS": `^\d{3}$`,
+	"IN": `^\d{6}$`,
+	"ID": `^\d{5}$`,
+	"IL": `^\d{5}$`,
+	"JO": `^\d{5}$`,
+	"KZ": `^\d{6}$`,
+	"KE": `^\d{5}$`,
+	"KW": `^\d{5}$`,
+	"LA": `^\d{5}$`,
+	"LV": `^\d{4}$`,
+	"LB": `^(\d{4}([ ]?\d{4})?)?$`,
+	"LI": `^(948[5-9])|(949[0-7])$`,
+	"LT": `^\d{5}$`,
+	"LU": `^\d{4}$`,
+	"MK": `^\d{4}$`,
+	"MY": `^\d{5}$`,
+	"MV": `^\d{5}$`,
+	"MT": `^[A-Z]{3}[ ]?\d{2,4}$`,
+	"MU": `^(\d{3}[A-Z]{2}\d{3})?$`,
+	"MX": `^\d{5}$`,
+	"MD": `^\d{4}$`,
+	"MC": `^980\d{2}$`,
+	"MA": `^\d{5}$`,
+	"NP": `^\d{5}$`,
+	"NZ": `^\d{4}$`,
+	"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`,
+	"NG": `^(\d{6})?$`,
+	"OM": `^(PC )?\d{3}$`,
+	"PK": `^\d{5}$`,
+	"PY": `^\d{4}$`,
+	"PH": `^\d{4}$`,
+	"PL": `^\d{2}-\d{3}$`,
+	"PR": `^00[679]\d{2}([ \-]\d{4})?$`,
+	"RO": `^\d{6}$`,
+	"RU": `^\d{6}$`,
+	"SM": `^4789\d$`,
+	"SA": `^\d{5}$`,
+	"SN": `^\d{5}$`,
+	"SK": `^\d{3}[ ]?\d{2}$`,
+	"SI": `^\d{4}$`,
+	"ZA": `^\d{4}$`,
+	"LK": `^\d{5}$`,
+	"TJ": `^\d{6}$`,
+	"TH": `^\d{5}$`,
+	"TN": `^\d{4}$`,
+	"TR": `^\d{5}$`,
+	"TM": `^\d{6}$`,
+	"UA": `^\d{5}$`,
+	"UY": `^\d{5}$`,
+	"UZ": `^\d{6}$`,
+	"VA": `^00120$`,
+	"VE": `^\d{4}$`,
+	"ZM": `^\d{5}$`,
+	"AS": `^96799$`,
+	"CC": `^6799$`,
+	"CK": `^\d{4}$`,
+	"RS": `^\d{6}$`,
+	"ME": `^8\d{4}$`,
+	"CS": `^\d{5}$`,
+	"YU": `^\d{5}$`,
+	"CX": `^6798$`,
+	"ET": `^\d{4}$`,
+	"FK": `^FIQQ 1ZZ$`,
+	"NF": `^2899$`,
+	"FM": `^(9694[1-4])([ \-]\d{4})?$`,
+	"GF": `^9[78]3\d{2}$`,
+	"GN": `^\d{3}$`,
+	"GP": `^9[78][01]\d{2}$`,
+	"GS": `^SIQQ 1ZZ$`,
+	"GU": `^969[123]\d([ \-]\d{4})?$`,
+	"GW": `^\d{4}$`,
+	"HM": `^\d{4}$`,
+	"IQ": `^\d{5}$`,
+	"KG": `^\d{6}$`,
+	"LR": `^\d{4}$`,
+	"LS": `^\d{3}$`,
+	"MG": `^\d{3}$`,
+	"MH": `^969[67]\d([ \-]\d{4})?$`,
+	"MN": `^\d{6}$`,
+	"MP": `^9695[012]([ \-]\d{4})?$`,
+	"MQ": `^9[78]2\d{2}$`,
+	"NC": `^988\d{2}$`,
+	"NE": `^\d{4}$`,
+	"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`,
+	"VN": `^[0-9]{1,6}$`,
+	"PF": `^987\d{2}$`,
+	"PG": `^\d{3}$`,
+	"PM": `^9[78]5\d{2}$`,
+	"PN": `^PCRN 1ZZ$`,
+	"PW": `^96940$`,
+	"RE": `^9[78]4\d{2}$`,
+	"SH": `^(ASCN|STHL) 1ZZ$`,
+	"SJ": `^\d{4}$`,
+	"SO": `^\d{5}$`,
+	"SZ": `^[HLMS]\d{3}$`,
+	"TC": `^TKCA 1ZZ$`,
+	"WF": `^986\d{2}$`,
+	"XK": `^\d{5}$`,
+	"YT": `^976\d{2}$`,
+}
+
+var postCodeRegexDict = map[string]*regexp.Regexp{}
+
+func init() {
+	for countryCode, pattern := range postCodePatternDict {
+		postCodeRegexDict[countryCode] = regexp.MustCompile(pattern)
+	}
+}
diff --git a/translations/en/en.go b/translations/en/en.go
index 1fdea95..3bbca51 100644
--- a/translations/en/en.go
+++ b/translations/en/en.go
@@ -16,7 +16,6 @@ import (
 // RegisterDefaultTranslations registers a set of default translations
 // for all built in tag's in validator; you may add your own as desired.
 func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) {
-
 	translations := []struct {
 		tag             string
 		translation     string
@@ -32,7 +31,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "len",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("len-string", "{0} must be {1} in length", false); err != nil {
 					return
 				}
@@ -61,10 +59,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				}
 
 				return
-
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 
@@ -123,7 +119,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "min",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("min-string", "{0} must be at least {1} in length", false); err != nil {
 					return
 				}
@@ -152,10 +147,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				}
 
 				return
-
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 
@@ -214,7 +207,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "max",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("max-string", "{0} must be a maximum of {1} in length", false); err != nil {
 					return
 				}
@@ -243,10 +235,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				}
 
 				return
-
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 
@@ -307,7 +297,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} is not equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					fmt.Printf("warning: error translating FieldError: %#v", fe)
@@ -322,7 +311,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} should not be equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					fmt.Printf("warning: error translating FieldError: %#v", fe)
@@ -335,7 +323,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "lt",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("lt-string", "{0} must be less than {1} in length", false); err != nil {
 					return
 				}
@@ -369,10 +356,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				}
 
 				return
-
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 				var f64 float64
@@ -380,7 +365,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				var kind reflect.Kind
 
 				fn := func() (err error) {
-
 					if idx := strings.Index(fe.Param(), "."); idx != -1 {
 						digits = uint64(len(fe.Param()[idx+1:]))
 					}
@@ -456,7 +440,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "lte",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("lte-string", "{0} must be at maximum {1} in length", false); err != nil {
 					return
 				}
@@ -492,7 +475,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				return
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 				var f64 float64
@@ -500,7 +482,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				var kind reflect.Kind
 
 				fn := func() (err error) {
-
 					if idx := strings.Index(fe.Param(), "."); idx != -1 {
 						digits = uint64(len(fe.Param()[idx+1:]))
 					}
@@ -576,7 +557,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "gt",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("gt-string", "{0} must be greater than {1} in length", false); err != nil {
 					return
 				}
@@ -612,7 +592,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				return
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 				var f64 float64
@@ -620,7 +599,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				var kind reflect.Kind
 
 				fn := func() (err error) {
-
 					if idx := strings.Index(fe.Param(), "."); idx != -1 {
 						digits = uint64(len(fe.Param()[idx+1:]))
 					}
@@ -696,7 +674,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		{
 			tag: "gte",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
 				if err = ut.Add("gte-string", "{0} must be at least {1} in length", false); err != nil {
 					return
 				}
@@ -732,7 +709,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				return
 			},
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				var err error
 				var t string
 				var f64 float64
@@ -740,7 +716,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				var kind reflect.Kind
 
 				fn := func() (err error) {
-
 					if idx := strings.Index(fe.Param(), "."); idx != -1 {
 						digits = uint64(len(fe.Param()[idx+1:]))
 					}
@@ -818,7 +793,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -833,7 +807,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -848,7 +821,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} cannot be equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -863,7 +835,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be greater than {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -878,7 +849,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be greater than or equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -893,7 +863,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be less than {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -908,7 +877,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be less than or equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -923,7 +891,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} cannot be equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -938,7 +905,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be greater than {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -953,7 +919,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be greater than or equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -968,7 +933,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be less than {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -983,7 +947,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must be less than or equal to {1}",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1073,7 +1036,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must contain the text '{1}'",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1088,7 +1050,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} must contain at least one of the following characters '{1}'",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1103,7 +1064,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} cannot contain the text '{1}'",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1118,7 +1078,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} cannot contain any of the following characters '{1}'",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1133,7 +1092,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} cannot contain the following '{1}'",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
-
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1325,8 +1283,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			tag:         "json",
 			translation: "{0} must be a valid json string",
 			override:    false,
-    },
-    {
+		},
+		{
 			tag:         "lowercase",
 			translation: "{0} must be a lowercase string",
 			override:    false,
@@ -1341,7 +1299,34 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			translation: "{0} does not match the {1} format",
 			override:    false,
 			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				if err != nil {
+					log.Printf("warning: error translating FieldError: %#v", fe)
+					return fe.(error).Error()
+				}
 
+				return t
+			},
+		},
+		{
+			tag:         "postcode_iso3166_alpha2",
+			translation: "{0} does not match postcode format of {1} country",
+			override:    false,
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				if err != nil {
+					log.Printf("warning: error translating FieldError: %#v", fe)
+					return fe.(error).Error()
+				}
+
+				return t
+			},
+		},
+		{
+			tag:         "postcode_iso3166_alpha2_field",
+			translation: "{0} does not match postcode format of country in {1} field",
+			override:    false,
+			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
 				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
 				if err != nil {
 					log.Printf("warning: error translating FieldError: %#v", fe)
@@ -1356,17 +1341,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 	for _, t := range translations {
 
 		if t.customTransFunc != nil && t.customRegisFunc != nil {
-
 			err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc)
-
 		} else if t.customTransFunc != nil && t.customRegisFunc == nil {
-
 			err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc)
-
 		} else if t.customTransFunc == nil && t.customRegisFunc != nil {
-
 			err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc)
-
 		} else {
 			err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc)
 		}
@@ -1380,21 +1359,16 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 }
 
 func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc {
-
 	return func(ut ut.Translator) (err error) {
-
 		if err = ut.Add(tag, translation, override); err != nil {
 			return
 		}
 
 		return
-
 	}
-
 }
 
 func translateFunc(ut ut.Translator, fe validator.FieldError) string {
-
 	t, err := ut.T(fe.Tag(), fe.Field())
 	if err != nil {
 		log.Printf("warning: error translating FieldError: %#v", fe)


Test patch:
diff --git a/translations/en/en_test.go b/translations/en/en_test.go
index 2b113c6..fd8df77 100644
--- a/translations/en/en_test.go
+++ b/translations/en/en_test.go
@@ -11,7 +11,6 @@ import (
 )
 
 func TestTranslations(t *testing.T) {
-
 	eng := english.New()
 	uni := ut.New(eng, eng)
 	trans, _ := uni.GetTranslator("en")
@@ -145,6 +144,9 @@ func TestTranslations(t *testing.T) {
 		LowercaseString   string            `validate:"lowercase"`
 		UppercaseString   string            `validate:"uppercase"`
 		Datetime          string            `validate:"datetime=2006-01-02"`
+		PostCode          string            `validate:"postcode_iso3166_alpha2=SG"`
+		PostCodeCountry   string
+		PostCodeByField   string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
 	}
 
 	var test Test
@@ -656,6 +658,14 @@ func TestTranslations(t *testing.T) {
 			ns:       "Test.Datetime",
 			expected: "Datetime does not match the 2006-01-02 format",
 		},
+		{
+			ns:       "Test.PostCode",
+			expected: "PostCode does not match postcode format of SG country",
+		},
+		{
+			ns:       "Test.PostCodeByField",
+			expected: "PostCodeByField does not match postcode format of country in PostCodeCountry field",
+		},
 	}
 
 	for _, tt := range tests {
@@ -672,5 +682,4 @@ func TestTranslations(t *testing.T) {
 		NotEqual(t, fe, nil)
 		Equal(t, tt.expected, fe.Translate(trans))
 	}
-
 }
diff --git a/validator_test.go b/validator_test.go
index 19dac53..be967d4 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -14,6 +14,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/go-playground/assert/v2"
 	. "github.com/go-playground/assert/v2"
 	"github.com/go-playground/locales/en"
 	"github.com/go-playground/locales/fr"
@@ -108,7 +109,6 @@ type TestSlice struct {
 }
 
 func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) {
-
 	errs := err.(ValidationErrors)
 
 	found := false
@@ -150,7 +150,6 @@ func AssertDeepError(t *testing.T, err error, nsKey, structNsKey, field, structF
 }
 
 func getError(err error, nsKey, structNsKey string) FieldError {
-
 	errs := err.(ValidationErrors)
 
 	var fe FieldError
@@ -170,7 +169,6 @@ type valuer struct {
 }
 
 func (v valuer) Value() (driver.Value, error) {
-
 	if v.Name == "errorme" {
 		panic("SQL Driver Valuer error: some kind of error")
 		// return nil, errors.New("some kind of error")
@@ -189,7 +187,6 @@ type MadeUpCustomType struct {
 }
 
 func ValidateCustomType(field reflect.Value) interface{} {
-
 	if cust, ok := field.Interface().(MadeUpCustomType); ok {
 
 		if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
@@ -203,7 +200,6 @@ func ValidateCustomType(field reflect.Value) interface{} {
 }
 
 func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
-
 	if i, ok := field.Interface().(int); ok {
 		if i == 1 {
 			return "1"
@@ -223,7 +219,6 @@ type CustomMadeUpStruct struct {
 }
 
 func ValidateValuerType(field reflect.Value) interface{} {
-
 	if valuer, ok := field.Interface().(driver.Valuer); ok {
 
 		val, err := valuer.Value()
@@ -261,7 +256,6 @@ type TestStruct struct {
 }
 
 func StructValidationTestStructSuccess(sl StructLevel) {
-
 	st := sl.Current().Interface().(TestStruct)
 
 	if st.String != "good value" {
@@ -270,7 +264,6 @@ func StructValidationTestStructSuccess(sl StructLevel) {
 }
 
 func StructValidationTestStruct(sl StructLevel) {
-
 	st := sl.Current().Interface().(TestStruct)
 
 	if st.String != "bad value" {
@@ -279,7 +272,6 @@ func StructValidationTestStruct(sl StructLevel) {
 }
 
 func StructValidationNoTestStructCustomName(sl StructLevel) {
-
 	st := sl.Current().Interface().(TestStruct)
 
 	if st.String != "bad value" {
@@ -288,7 +280,6 @@ func StructValidationNoTestStructCustomName(sl StructLevel) {
 }
 
 func StructValidationTestStructInvalid(sl StructLevel) {
-
 	st := sl.Current().Interface().(TestStruct)
 
 	if st.String != "bad value" {
@@ -297,7 +288,6 @@ func StructValidationTestStructInvalid(sl StructLevel) {
 }
 
 func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
-
 	s := sl.Current().Interface().(TestStructReturnValidationErrors)
 
 	errs := sl.Validator().Struct(s.Inner1.Inner2)
@@ -309,7 +299,6 @@ func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
 }
 
 func StructValidationTestStructReturnValidationErrors2(sl StructLevel) {
-
 	s := sl.Current().Interface().(TestStructReturnValidationErrors)
 
 	errs := sl.Validator().Struct(s.Inner1.Inner2)
@@ -337,7 +326,6 @@ type StructLevelInvalidErr struct {
 }
 
 func StructLevelInvalidError(sl StructLevel) {
-
 	top := sl.Top().Interface().(StructLevelInvalidErr)
 	s := sl.Current().Interface().(StructLevelInvalidErr)
 
@@ -359,7 +347,6 @@ func float64Ptr(v float64) *float64 {
 }
 
 func TestStructLevelInvalidError(t *testing.T) {
-
 	validate := New()
 	validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{})
 
@@ -383,7 +370,6 @@ func TestStructLevelInvalidError(t *testing.T) {
 }
 
 func TestNameNamespace(t *testing.T) {
-
 	type Inner2Namespace struct {
 		String []string `validate:"dive,required" json:"JSONString"`
 	}
@@ -432,7 +418,6 @@ func TestNameNamespace(t *testing.T) {
 }
 
 func TestAnonymous(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -500,7 +485,6 @@ func TestAnonymous(t *testing.T) {
 }
 
 func TestAnonymousSameStructDifferentTags(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -545,7 +529,6 @@ func TestAnonymousSameStructDifferentTags(t *testing.T) {
 }
 
 func TestStructLevelReturnValidationErrors(t *testing.T) {
-
 	validate := New()
 	validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
 
@@ -575,7 +558,6 @@ func TestStructLevelReturnValidationErrors(t *testing.T) {
 }
 
 func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -632,7 +614,6 @@ func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
 }
 
 func TestStructLevelValidations(t *testing.T) {
-
 	v1 := New()
 	v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
 
@@ -666,7 +647,6 @@ func TestStructLevelValidations(t *testing.T) {
 }
 
 func TestAliasTags(t *testing.T) {
-
 	validate := New()
 	validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla")
 
@@ -714,7 +694,6 @@ func TestAliasTags(t *testing.T) {
 }
 
 func TestNilValidator(t *testing.T) {
-
 	type TestStruct struct {
 		Test string `validate:"required"`
 	}
@@ -724,7 +703,6 @@ func TestNilValidator(t *testing.T) {
 	var val *Validate
 
 	fn := func(fl FieldLevel) bool {
-
 		return fl.Parent().String() == fl.Field().String()
 	}
 
@@ -1971,7 +1949,6 @@ func TestCrossStructEqFieldValidation(t *testing.T) {
 }
 
 func TestCrossNamespaceFieldValidation(t *testing.T) {
-
 	type SliceStruct struct {
 		Name string
 	}
@@ -2209,7 +2186,6 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
 }
 
 func TestExistsValidation(t *testing.T) {
-
 	jsonText := "{ \"truthiness2\": true }"
 
 	type Thing struct {
@@ -2240,7 +2216,6 @@ func TestExistsValidation(t *testing.T) {
 }
 
 func TestSQLValue2Validation(t *testing.T) {
-
 	validate := New()
 	validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
 	validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
@@ -2291,7 +2266,6 @@ func TestSQLValue2Validation(t *testing.T) {
 }
 
 func TestSQLValueValidation(t *testing.T) {
-
 	validate := New()
 	validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
 	validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
@@ -2969,7 +2943,6 @@ func TestUnixAddrValidation(t *testing.T) {
 }
 
 func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
-
 	validate := New()
 
 	var m map[string]string
@@ -3047,7 +3020,6 @@ func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
 }
 
 func TestDatePtrValidationIssueValidation(t *testing.T) {
-
 	type Test struct {
 		LastViewed *time.Time
 		Reminder   *time.Time
@@ -3099,7 +3071,6 @@ func TestBadKeyValidation(t *testing.T) {
 }
 
 func TestInterfaceErrValidation(t *testing.T) {
-
 	var v2 interface{} = 1
 	var v1 interface{} = v2
 
@@ -3273,7 +3244,6 @@ func TestInterfaceErrValidation(t *testing.T) {
 }
 
 func TestMapDiveValidation(t *testing.T) {
-
 	validate := New()
 
 	n := map[int]interface{}{0: nil}
@@ -3396,7 +3366,6 @@ func TestMapDiveValidation(t *testing.T) {
 }
 
 func TestArrayDiveValidation(t *testing.T) {
-
 	validate := New()
 
 	arr := []string{"ok", "", "ok"}
@@ -4405,7 +4374,6 @@ func TestISBN10Validation(t *testing.T) {
 }
 
 func TestExcludesRuneValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"excludesrune=☻"`
 		Tag         string
@@ -4433,7 +4401,6 @@ func TestExcludesRuneValidation(t *testing.T) {
 }
 
 func TestExcludesAllValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"excludesall=@!{}[]"`
 		Tag         string
@@ -4479,7 +4446,6 @@ func TestExcludesAllValidation(t *testing.T) {
 }
 
 func TestExcludesValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"excludes=@"`
 		Tag         string
@@ -4507,7 +4473,6 @@ func TestExcludesValidation(t *testing.T) {
 }
 
 func TestContainsRuneValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"containsrune=☻"`
 		Tag         string
@@ -4535,7 +4500,6 @@ func TestContainsRuneValidation(t *testing.T) {
 }
 
 func TestContainsAnyValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"containsany=@!{}[]"`
 		Tag         string
@@ -4563,7 +4527,6 @@ func TestContainsAnyValidation(t *testing.T) {
 }
 
 func TestContainsValidation(t *testing.T) {
-
 	tests := []struct {
 		Value       string `validate:"contains=@"`
 		Tag         string
@@ -5149,7 +5112,6 @@ func TestOneOfValidation(t *testing.T) {
 }
 
 func TestBase64Validation(t *testing.T) {
-
 	validate := New()
 
 	s := "dW5pY29ybg=="
@@ -5253,7 +5215,6 @@ func TestFileValidation(t *testing.T) {
 }
 
 func TestEthereumAddressValidation(t *testing.T) {
-
 	validate := New()
 
 	tests := []struct {
@@ -5307,7 +5268,6 @@ func TestEthereumAddressValidation(t *testing.T) {
 }
 
 func TestBitcoinAddressValidation(t *testing.T) {
-
 	validate := New()
 
 	tests := []struct {
@@ -5417,7 +5377,6 @@ func TestBitcoinAddressValidation(t *testing.T) {
 }
 
 func TestBitcoinBech32AddressValidation(t *testing.T) {
-
 	validate := New()
 
 	tests := []struct {
@@ -5468,7 +5427,6 @@ func TestBitcoinBech32AddressValidation(t *testing.T) {
 }
 
 func TestNoStructLevelValidation(t *testing.T) {
-
 	type Inner struct {
 		Test string `validate:"len=5"`
 	}
@@ -5500,7 +5458,6 @@ func TestNoStructLevelValidation(t *testing.T) {
 }
 
 func TestStructOnlyValidation(t *testing.T) {
-
 	type Inner struct {
 		Test string `validate:"len=5"`
 	}
@@ -6566,7 +6523,6 @@ func TestValidateByTagAndValue(t *testing.T) {
 	Equal(t, errs, nil)
 
 	fn := func(fl FieldLevel) bool {
-
 		return fl.Parent().String() == fl.Field().String()
 	}
 
@@ -6584,9 +6540,7 @@ func TestValidateByTagAndValue(t *testing.T) {
 }
 
 func TestAddFunctions(t *testing.T) {
-
 	fn := func(fl FieldLevel) bool {
-
 		return true
 	}
 
@@ -6615,7 +6569,6 @@ func TestAddFunctions(t *testing.T) {
 }
 
 func TestChangeTag(t *testing.T) {
-
 	validate := New()
 	validate.SetTagName("val")
 
@@ -7262,8 +7215,7 @@ func TestIsLte(t *testing.T) {
 }
 
 func TestUrnRFC2141(t *testing.T) {
-
-	var tests = []struct {
+	tests := []struct {
 		param    string
 		expected bool
 	}{
@@ -7339,8 +7291,7 @@ func TestUrnRFC2141(t *testing.T) {
 }
 
 func TestUrl(t *testing.T) {
-
-	var tests = []struct {
+	tests := []struct {
 		param    string
 		expected bool
 	}{
@@ -7407,8 +7358,7 @@ func TestUrl(t *testing.T) {
 }
 
 func TestUri(t *testing.T) {
-
-	var tests = []struct {
+	tests := []struct {
 		param    string
 		expected bool
 	}{
@@ -7474,7 +7424,6 @@ func TestUri(t *testing.T) {
 }
 
 func TestOrTag(t *testing.T) {
-
 	validate := New()
 
 	s := "rgba(0,31,255,0.5)"
@@ -7504,7 +7453,7 @@ func TestOrTag(t *testing.T) {
 	Equal(t, errs, nil)
 
 	s = "green"
-	errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block
+	errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") // should fail on first validation block
 	NotEqual(t, errs, nil)
 	ve := errs.(ValidationErrors)
 	Equal(t, len(ve), 1)
@@ -7517,7 +7466,6 @@ func TestOrTag(t *testing.T) {
 
 	v2 := New()
 	v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
-
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
 
 		if name == "-" {
@@ -7542,7 +7490,6 @@ func TestOrTag(t *testing.T) {
 }
 
 func TestHsla(t *testing.T) {
-
 	validate := New()
 
 	s := "hsla(360,100%,100%,1)"
@@ -7589,7 +7536,6 @@ func TestHsla(t *testing.T) {
 }
 
 func TestHsl(t *testing.T) {
-
 	validate := New()
 
 	s := "hsl(360,100%,50%)"
@@ -7627,7 +7573,6 @@ func TestHsl(t *testing.T) {
 }
 
 func TestRgba(t *testing.T) {
-
 	validate := New()
 
 	s := "rgba(0,31,255,0.5)"
@@ -7673,7 +7618,6 @@ func TestRgba(t *testing.T) {
 }
 
 func TestRgb(t *testing.T) {
-
 	validate := New()
 
 	s := "rgb(0,31,255)"
@@ -7715,7 +7659,6 @@ func TestRgb(t *testing.T) {
 }
 
 func TestEmail(t *testing.T) {
-
 	validate := New()
 
 	s := "test@mail.com"
@@ -7783,7 +7726,6 @@ func TestEmail(t *testing.T) {
 }
 
 func TestHexColor(t *testing.T) {
-
 	validate := New()
 
 	s := "#fff"
@@ -7811,7 +7753,6 @@ func TestHexColor(t *testing.T) {
 }
 
 func TestHexadecimal(t *testing.T) {
-
 	validate := New()
 
 	s := "ff0044"
@@ -7838,7 +7779,6 @@ func TestHexadecimal(t *testing.T) {
 }
 
 func TestNumber(t *testing.T) {
-
 	validate := New()
 
 	s := "1"
@@ -7886,7 +7826,6 @@ func TestNumber(t *testing.T) {
 }
 
 func TestNumeric(t *testing.T) {
-
 	validate := New()
 
 	s := "1"
@@ -7929,7 +7868,6 @@ func TestNumeric(t *testing.T) {
 }
 
 func TestAlphaNumeric(t *testing.T) {
-
 	validate := New()
 
 	s := "abcd123"
@@ -7947,7 +7885,6 @@ func TestAlphaNumeric(t *testing.T) {
 }
 
 func TestAlpha(t *testing.T) {
-
 	validate := New()
 
 	s := "abcd"
@@ -7977,11 +7914,9 @@ func TestAlpha(t *testing.T) {
 	errs = validate.Var(1, "alpha")
 	NotEqual(t, errs, nil)
 	AssertError(t, errs, "", "", "", "", "alpha")
-
 }
 
 func TestStructStringValidation(t *testing.T) {
-
 	validate := New()
 
 	tSuccess := &TestString{
@@ -8063,7 +7998,6 @@ func TestStructStringValidation(t *testing.T) {
 }
 
 func TestStructInt32Validation(t *testing.T) {
-
 	type TestInt32 struct {
 		Required  int `validate:"required"`
 		Len       int `validate:"len=10"`
@@ -8127,7 +8061,6 @@ func TestStructInt32Validation(t *testing.T) {
 }
 
 func TestStructUint64Validation(t *testing.T) {
-
 	validate := New()
 
 	tSuccess := &TestUint64{
@@ -8167,7 +8100,6 @@ func TestStructUint64Validation(t *testing.T) {
 }
 
 func TestStructFloat64Validation(t *testing.T) {
-
 	validate := New()
 
 	tSuccess := &TestFloat64{
@@ -8207,7 +8139,6 @@ func TestStructFloat64Validation(t *testing.T) {
 }
 
 func TestStructSliceValidation(t *testing.T) {
-
 	validate := New()
 
 	tSuccess := &TestSlice{
@@ -8257,11 +8188,9 @@ func TestStructSliceValidation(t *testing.T) {
 
 	_, ok := fe.Value().([]int)
 	Equal(t, ok, true)
-
 }
 
 func TestInvalidStruct(t *testing.T) {
-
 	validate := New()
 
 	s := &SubTest{
@@ -8286,7 +8215,6 @@ func TestInvalidStruct(t *testing.T) {
 }
 
 func TestInvalidValidatorFunction(t *testing.T) {
-
 	validate := New()
 
 	s := &SubTest{
@@ -8297,7 +8225,6 @@ func TestInvalidValidatorFunction(t *testing.T) {
 }
 
 func TestCustomFieldName(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0]
@@ -8341,7 +8268,6 @@ func TestCustomFieldName(t *testing.T) {
 }
 
 func TestMutipleRecursiveExtractStructCache(t *testing.T) {
-
 	validate := New()
 
 	type Recursive struct {
@@ -8358,7 +8284,6 @@ func TestMutipleRecursiveExtractStructCache(t *testing.T) {
 	ptr := fmt.Sprintf("%p", sc)
 
 	for i := 0; i < 100; i++ {
-
 		go func() {
 			<-proceed
 			sc := validate.extractStructCache(current, name)
@@ -8371,7 +8296,6 @@ func TestMutipleRecursiveExtractStructCache(t *testing.T) {
 
 // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
 func TestPointerAndOmitEmpty(t *testing.T) {
-
 	validate := New()
 
 	type Test struct {
@@ -8417,7 +8341,6 @@ func TestPointerAndOmitEmpty(t *testing.T) {
 }
 
 func TestRequired(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -8441,7 +8364,6 @@ func TestRequired(t *testing.T) {
 }
 
 func TestBoolEqual(t *testing.T) {
-
 	validate := New()
 
 	type Test struct {
@@ -8469,16 +8391,13 @@ func TestTranslations(t *testing.T) {
 	validate := New()
 	err := validate.RegisterTranslation("required", trans,
 		func(ut ut.Translator) (err error) {
-
 			// using this stype because multiple translation may have to be added for the full translation
 			if err = ut.Add("required", "{0} is a required field", false); err != nil {
 				return
 			}
 
 			return
-
 		}, func(ut ut.Translator, fe FieldError) string {
-
 			t, err := ut.T(fe.Tag(), fe.Field())
 			if err != nil {
 				fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@@ -8491,16 +8410,13 @@ func TestTranslations(t *testing.T) {
 
 	err = validate.RegisterTranslation("required", fr,
 		func(ut ut.Translator) (err error) {
-
 			// using this stype because multiple translation may have to be added for the full translation
 			if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil {
 				return
 			}
 
 			return
-
 		}, func(ut ut.Translator, fe FieldError) string {
-
 			t, transErr := ut.T(fe.Tag(), fe.Field())
 			if transErr != nil {
 				fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@@ -8578,16 +8494,13 @@ func TestTranslationErrors(t *testing.T) {
 	validate := New()
 	err = validate.RegisterTranslation("required", trans,
 		func(ut ut.Translator) (err error) {
-
 			// using this stype because multiple translation may have to be added for the full translation
 			if err = ut.Add("required", "{0} is a required field", false); err != nil {
 				return
 			}
 
 			return
-
 		}, func(ut ut.Translator, fe FieldError) string {
-
 			t, err := ut.T(fe.Tag(), fe.Field())
 			if err != nil {
 				fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@@ -8602,7 +8515,6 @@ func TestTranslationErrors(t *testing.T) {
 }
 
 func TestStructFiltered(t *testing.T) {
-
 	p1 := func(ns []byte) bool {
 		if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) {
 			return false
@@ -8768,7 +8680,6 @@ func TestStructFiltered(t *testing.T) {
 }
 
 func TestRequiredPtr(t *testing.T) {
-
 	type Test struct {
 		Bool *bool `validate:"required"`
 	}
@@ -8902,7 +8813,6 @@ func TestAlphaUnicodeValidation(t *testing.T) {
 }
 
 func TestAlphanumericUnicodeValidation(t *testing.T) {
-
 	tests := []struct {
 		param    string
 		expected bool
@@ -8945,7 +8855,6 @@ func TestAlphanumericUnicodeValidation(t *testing.T) {
 }
 
 func TestArrayStructNamespace(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -8974,7 +8883,6 @@ func TestArrayStructNamespace(t *testing.T) {
 }
 
 func TestMapStructNamespace(t *testing.T) {
-
 	validate := New()
 	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
 		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -9655,7 +9563,6 @@ func TestURLEncodedValidation(t *testing.T) {
 }
 
 func TestKeys(t *testing.T) {
-
 	type Test struct {
 		Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"`
 		Test2 map[int]int       `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4"             json:"test2"`
@@ -9824,7 +9731,6 @@ func TestKeysCustomValidation(t *testing.T) {
 }
 
 func TestKeyOrs(t *testing.T) {
-
 	type Test struct {
 		Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"`
 	}
@@ -10602,7 +10508,6 @@ func TestRequiredWithAll(t *testing.T) {
 }
 
 func TestRequiredWithout(t *testing.T) {
-
 	type Inner struct {
 		Field *string
 	}
@@ -10668,7 +10573,6 @@ func TestRequiredWithout(t *testing.T) {
 }
 
 func TestRequiredWithoutAll(t *testing.T) {
-
 	fieldVal := "test"
 	test := struct {
 		Field1 string            `validate:"omitempty" json:"field_1"`
@@ -10725,7 +10629,6 @@ func TestLookup(t *testing.T) {
 }
 
 func TestAbilityToValidateNils(t *testing.T) {
-
 	type TestStruct struct {
 		Test *string `validate:"nil"`
 	}
@@ -10867,7 +10770,6 @@ func TestJSONValidation(t *testing.T) {
 }
 
 func Test_hostnameport_validator(t *testing.T) {
-
 	type Host struct {
 		Addr string `validate:"hostname_port"`
 	}
@@ -10969,7 +10871,6 @@ func TestUppercaseValidation(t *testing.T) {
 	PanicMatches(t, func() {
 		_ = validate.Var(2, "uppercase")
 	}, "Bad field type int")
-
 }
 
 func TestDatetimeValidation(t *testing.T) {
@@ -11225,42 +11126,154 @@ func TestBCP47LanguageTagValidation(t *testing.T) {
 }
 
 func TestBicIsoFormatValidation(t *testing.T) {
-	tests := []struct {
-		value    string `validate:"bic"`
-		tag      string
-		expected bool
-	}{
-		{"SBICKEN1345", "bic", true},
-		{"SBICKEN1", "bic", true},
-		{"SBICKENY", "bic", true},
-		{"SBICKEN1YYP", "bic", true},
-		{"SBIC23NXXX", "bic", false},
-		{"S23CKENXXXX", "bic", false},
-		{"SBICKENXX", "bic", false},
-		{"SBICKENXX9", "bic", false},
-		{"SBICKEN13458", "bic", false},
-		{"SBICKEN", "bic", false},
-	}
-
-	validate := New()
-
-	for i, test := range tests {
-
-		errs := validate.Var(test.value, test.tag)
-
-		if test.expected {
-			if !IsEqual(errs, nil) {
-				t.Fatalf("Index: %d bic failed Error: %s", i, errs)
-			}
-		} else {
-			if IsEqual(errs, nil) {
-				t.Fatalf("Index: %d bic failed Error: %s", i, errs)
-			} else {
-				val := getError(errs, "", "")
-				if val.Tag() != "bic" {
-					t.Fatalf("Index: %d bic failed Error: %s", i, errs)
-				}
-			}
-		}
-	}
-}
+ 	tests := []struct {
+ 		value    string `validate:"bic"`
+ 		tag      string
+ 		expected bool
+ 	}{
+ 		{"SBICKEN1345", "bic", true},
+ 		{"SBICKEN1", "bic", true},
+ 		{"SBICKENY", "bic", true},
+ 		{"SBICKEN1YYP", "bic", true},
+ 		{"SBIC23NXXX", "bic", false},
+ 		{"S23CKENXXXX", "bic", false},
+ 		{"SBICKENXX", "bic", false},
+ 		{"SBICKENXX9", "bic", false},
+ 		{"SBICKEN13458", "bic", false},
+ 		{"SBICKEN", "bic", false},
+ 	}
+
+ 	validate := New()
+
+ 	for i, test := range tests {
+
+ 		errs := validate.Var(test.value, test.tag)
+
+ 		if test.expected {
+ 			if !IsEqual(errs, nil) {
+ 				t.Fatalf("Index: %d bic failed Error: %s", i, errs)
+ 			}
+ 		} else {
+ 			if IsEqual(errs, nil) {
+ 				t.Fatalf("Index: %d bic failed Error: %s", i, errs)
+ 			} else {
+ 				val := getError(errs, "", "")
+ 				if val.Tag() != "bic" {
+ 					t.Fatalf("Index: %d bic failed Error: %s", i, errs)
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+
+func TestPostCodeByIso3166Alpha2(t *testing.T) {
+ 	tests := map[string][]struct {
+ 		value    string
+ 		expected bool
+ 	}{
+ 		"VN": {
+ 			{"ABC", false},
+ 			{"700000", true},
+ 			{"A1", false},
+ 		},
+ 		"GB": {
+ 			{"EC1A 1BB", true},
+ 			{"CF10 1B1H", false},
+ 		},
+ 		"VI": {
+ 			{"00803", true},
+ 			{"1234567", false},
+ 		},
+ 		"LC": { // not support regexp for post code
+ 			{"123456", false},
+ 		},
+ 		"XX": { // not support country
+ 			{"123456", false},
+ 		},
+ 	}
+
+ 	validate := New()
+
+ 	for cc, ccTests := range tests {
+ 		for i, test := range ccTests {
+ 			errs := validate.Var(test.value, fmt.Sprintf("postcode_iso3166_alpha2=%s", cc))
+
+ 			if test.expected {
+ 				if !IsEqual(errs, nil) {
+ 					t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
+ 				}
+ 			} else {
+ 				if IsEqual(errs, nil) {
+ 					t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
+ 				}
+ 			}
+ 		}
+ 	}
+ }
+
+ func TestPostCodeByIso3166Alpha2Field(t *testing.T) {
+ 	tests := []struct {
+ 		Value       string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
+ 		CountryCode interface{}
+ 		expected    bool
+ 	}{
+ 		{"ABC", "VN", false},
+ 		{"700000", "VN", true},
+ 		{"A1", "VN", false},
+ 		{"EC1A 1BB", "GB", true},
+ 		{"CF10 1B1H", "GB", false},
+ 		{"00803", "VI", true},
+ 		{"1234567", "VI", false},
+ 		{"123456", "LC", false}, // not support regexp for post code
+ 		{"123456", "XX", false}, // not support country
+ 	}
+
+ 	validate := New()
+
+ 	for i, test := range tests {
+ 		errs := validate.Struct(test)
+ 		if test.expected {
+ 			if !IsEqual(errs, nil) {
+ 				t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
+ 			}
+ 		} else {
+ 			if IsEqual(errs, nil) {
+ 				t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
+ 			}
+ 		}
+ 	}
+ }
+
+ func TestPostCodeByIso3166Alpha2Field_WrongField(t *testing.T) {
+ 	type test struct {
+ 		Value        string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
+ 		CountryCode1 interface{}
+ 		expected     bool
+ 	}
+
+ 	errs := New().Struct(test{"ABC", "VN", false})
+ 	assert.NotEqual(t, nil, errs)
+ }
+
+ func TestPostCodeByIso3166Alpha2Field_MissingParam(t *testing.T) {
+ 	type test struct {
+ 		Value        string `validate:"postcode_iso3166_alpha2_field="`
+ 		CountryCode1 interface{}
+ 		expected     bool
+ 	}
+
+ 	errs := New().Struct(test{"ABC", "VN", false})
+ 	assert.NotEqual(t, nil, errs)
+ }
+
+ func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
+ 	type test struct {
+ 		Value       string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
+ 		CountryCode interface{}
+ 		expected    bool
+ 	}
+ 	defer func() { recover() }()
+   
+  _ = New().Struct(test{"ABC", 123, false})
+ 	t.Errorf("Didn't panic as expected")
+ }