// Copyright 2019 getensh.com. All rights reserved. // Use of this source code is governed by getensh.com. package util import ( "regexp" ) const ( // 匹配大陆电话 cnPhonePattern = `((\d{3,4})-?)?` + // 区号 `\d{5,10}` + // 号码,95500等5位数的,7位,8位,以及400开头的10位数 `(-\d{1,4})?` // 分机号,分机号的连接符号不能省略。 // 匹配大陆手机号码 cnMobilePattern = `(0|\+?86)?` + // 匹配 0,86,+86 `(13[0-9]|` + // 130-139 `14[579]|` + // 145,147,149 `15[0-9]|` + // 150-159 `17[0-9]|` + // 170-179 `18[0-9]|` + // 180-189 `16[56]|` + // 165,1666 `19[0126789])` + // 191,198,199 `[0-9]{8}` // 匹配大陆手机号或是电话号码 cnTelPattern = "(" + cnPhonePattern + ")|(" + cnMobilePattern + ")" // 匹配邮箱 emailPattern = `^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$` // 匹配 IP4 ip4Pattern = `((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)` // 匹配 IP6,参考以下网页内容: // http://blog.csdn.net/jiangfeng08/article/details/7642018 ip6Pattern = `(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|` + `(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` + `(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` + `(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` + `(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` + `(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` + `(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` + `(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))` // 同时匹配 IP4 和 IP6 ipPattern = "(" + ip4Pattern + ")|(" + ip6Pattern + ")" // 匹配域名 domainPattern = `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}` // 匹配 URL urlPattern = `((https|http|ftp|rtsp|mms)?://)?` + // 协议 `(([0-9a-zA-Z]+:)?[0-9a-zA-Z_-]+@)?` + // pwd:user@ "(" + ipPattern + "|(" + domainPattern + "))" + // IP 或域名 `(:\d{1,5})?` + // 端口 `(/+[a-zA-Z0-9][a-zA-Z0-9_.-]*)*/*` + // path `(\?([a-zA-Z0-9_-]+(=.*&?)*)*)*` // query idCertPattern = `^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$` ) var ( email = regexpCompile(emailPattern) ip4 = regexpCompile(ip4Pattern) ip6 = regexpCompile(ip6Pattern) ip = regexpCompile(ipPattern) url = regexpCompile(urlPattern) cnPhone = regexpCompile(cnPhonePattern) cnMobile = regexpCompile(cnMobilePattern) cnTel = regexpCompile(cnTelPattern) cnIdCert = regexpCompile(idCertPattern) ) func regexpCompile(str string) *regexp.Regexp { return regexp.MustCompile("^" + str + "$") } // 判断val是否能正确匹配exp中的正则表达式。 // val可以是[]byte, []rune, string类型。 func isMatch(exp *regexp.Regexp, val interface{}) bool { switch v := val.(type) { case []rune: return exp.MatchString(string(v)) case []byte: return exp.Match(v) case string: return exp.MatchString(v) default: return false } } // IsCNPhone 验证中国大陆的电话号码。支持如下格式: // 0578-12345678-1234 // 057812345678-1234 // 若存在分机号,则分机号的连接符不能省略。 func IsCNPhone(val interface{}) bool { return isMatch(cnPhone, val) } // IsCNMobile 验证中国大陆的手机号码 func IsCNMobile(val interface{}) bool { return isMatch(cnMobile, val) } // IsCNTel 验证手机和电话类型 func IsCNTel(val interface{}) bool { return isMatch(cnTel, val) } // IsURL 验证一个值是否标准的URL格式。支持IP和域名等格式 func IsURL(val interface{}) bool { return isMatch(url, val) } // IsIP 验证一个值是否为IP,可验证IP4和IP6 func IsIP(val interface{}) bool { return isMatch(ip, val) } // IsIP6 验证一个值是否为IP6 func IsIP6(val interface{}) bool { return isMatch(ip6, val) } // IsIP4 验证一个值是滞为IP4 func IsIP4(val interface{}) bool { return isMatch(ip4, val) } // IsEmail 验证一个值是否匹配一个邮箱。 func IsEmail(val interface{}) bool { return isMatch(email, val) } // IsIdCert 验证一个值是否匹配身份证号码。 func IsIdCert(val interface{}) bool { return isMatch(cnIdCert, val) }