init
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 caixw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// Copyright 2014 by caixw, All rights reserved.
|
||||
// Use of this source code is governed by a MIT
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// 一些常用的验证函数
|
||||
package validator
|
||||
|
||||
const Version = "0.1.0.140928"
|
||||
Generated
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright 2014 by caixw, All rights reserved.
|
||||
// Use of this source code is governed by a MIT
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package validator
|
||||
|
||||
// 我国现行的身份证号码有两种标准:GB11643-1989、GB11643-1999:
|
||||
//
|
||||
// GB11643-1989为一代身份证,从左至右分别为:
|
||||
// ------------------------------------------------------------
|
||||
// | 6位行政区域代码 | 6位出生年日期(不含世纪数)| 3位顺序码 |
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
// GB11643-1999为二代身份证,从左至右分别为:
|
||||
// ------------------------------------------------------------
|
||||
// | 6位行政区域代码 | 8位出生日期 | 3位顺序码 | 1位检验码 |
|
||||
// ------------------------------------------------------------
|
||||
|
||||
var (
|
||||
// 校验位对应的规则。
|
||||
gb11643Map = []byte{'1', '0', 'x', '9', '8', '7', '6', '5', '4', '3', '2'}
|
||||
|
||||
// 前17位号码对应的权值,为一个固定数组。可由gb11643_test.getWeight()计算得到。
|
||||
gb11643Weight = []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||||
)
|
||||
|
||||
// 判断一个身份证是否符合gb11643标准。
|
||||
// 若是15位则当作一代身份证,仅简单地判断各位是否都是数字;
|
||||
// 若是18位则当作二代身份证,会计算校验位是否正确;
|
||||
// 其它位数都返回false。
|
||||
func IsGb11643(val interface{}) bool {
|
||||
switch v := val.(type) {
|
||||
case string:
|
||||
return IsGb11643Bytes([]byte(v))
|
||||
case []byte:
|
||||
return IsGb11643Bytes(v)
|
||||
case []rune:
|
||||
return IsGb11643Bytes([]byte(string(v)))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 判断一个身份证是否符合gb11643标准。
|
||||
func IsGb11643Bytes(val []byte) bool {
|
||||
if len(val) == 15 {
|
||||
// 15位,只检测是否包含非数字字符。
|
||||
for i := 0; i < 15; i++ {
|
||||
if val[i] < '0' || val[i] > '9' {
|
||||
return false
|
||||
}
|
||||
} // end for
|
||||
return true
|
||||
}
|
||||
|
||||
if len(val) != 18 {
|
||||
return false
|
||||
}
|
||||
|
||||
sum := 0
|
||||
for i := 0; i < 17; i++ {
|
||||
sum += (gb11643Weight[i] * int((val[i] - '0')))
|
||||
}
|
||||
if val[17] == 'X' {
|
||||
val[17] = 'x'
|
||||
}
|
||||
return gb11643Map[sum%11] == val[17]
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
// Copyright 2014 by caixw, All rights reserved.
|
||||
// Use of this source code is governed by a MIT
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package validator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// 有关ISBN的算法及其它相关内容,可参照http://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E6%A0%87%E5%87%86%E4%B9%A6%E5%8F%B7
|
||||
|
||||
// 判断是否为合法的ISBN串号。可以同时判断ISBN10和ISBN13
|
||||
func IsISBN(val interface{}) bool {
|
||||
var result []byte
|
||||
|
||||
switch v := val.(type) {
|
||||
case []byte:
|
||||
result = v
|
||||
case []rune:
|
||||
result = []byte(string(v))
|
||||
case string:
|
||||
result = []byte(v)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
if bytes.IndexByte(result, '-') > -1 {
|
||||
result = eraseMinus(result)
|
||||
}
|
||||
|
||||
switch len(result) {
|
||||
case 10:
|
||||
return isISBN10(result)
|
||||
case 13:
|
||||
return isISBN13(result)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为合法的ISBN10
|
||||
func IsISBN10(val []byte) bool {
|
||||
if bytes.IndexByte(val, '-') == -1 {
|
||||
return isISBN10(val)
|
||||
}
|
||||
return isISBN10(eraseMinus(val))
|
||||
}
|
||||
|
||||
// 判断是否为合法的ISBN13
|
||||
func IsISBN13(val []byte) bool {
|
||||
if bytes.IndexByte(val, '-') == -1 {
|
||||
return isISBN13(val)
|
||||
}
|
||||
return isISBN13(eraseMinus(val))
|
||||
}
|
||||
|
||||
// isbn10的校验位对应的值。
|
||||
var isbn10Map = []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'x', '0'}
|
||||
|
||||
func isISBN10(val []byte) bool {
|
||||
sum := 0
|
||||
for i := 0; i < 9; i++ {
|
||||
sum += int(val[i]-'0') * (10 - i)
|
||||
}
|
||||
|
||||
if val[9] == 'X' {
|
||||
val[9] = 'x'
|
||||
}
|
||||
|
||||
return isbn10Map[11-sum%11] == val[9]
|
||||
}
|
||||
|
||||
func isISBN13(val []byte) bool {
|
||||
sum := 0
|
||||
for i := 0; i < 12; i += 2 {
|
||||
sum += int(val[i] - '0')
|
||||
}
|
||||
|
||||
for i := 1; i < 12; i += 2 {
|
||||
sum += (int(val[i]-'0') * 3)
|
||||
}
|
||||
|
||||
return (10 - sum%10) == int(val[12]-'0')
|
||||
}
|
||||
|
||||
// 过滤减号(-)符号
|
||||
func eraseMinus(val []byte) []byte {
|
||||
offset := 0
|
||||
for k, v := range val {
|
||||
if v == '-' {
|
||||
offset += 1
|
||||
continue
|
||||
}
|
||||
|
||||
val[k-offset] = v
|
||||
}
|
||||
return val[0 : len(val)-offset]
|
||||
}
|
||||
Generated
Vendored
+123
@@ -0,0 +1,123 @@
|
||||
// Copyright 2014 by caixw, All rights reserved.
|
||||
// Use of this source code is governed by a MIT
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package validator
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
// 匹配大陆电话
|
||||
cnPhoneStr = `((\d{3,4})-?)?` + // 区号
|
||||
`\d{7,8}` + // 号码
|
||||
`(-\d{1,4})?` // 分机号,分机号的连接符号不能省略。
|
||||
|
||||
// 匹配大陆手机号码
|
||||
cnMobileStr = `(0|\+?86)?` + // 匹配 0,86,+86
|
||||
`(13[0-9]|` + // 130-139
|
||||
`14[57]|` + // 145,147
|
||||
`15[0-35-9]|` + // 150-153,155-159
|
||||
`17[0678]|` + // 170,176,177,17u
|
||||
`18[0-9])` + // 180-189
|
||||
`[0-9]{8}`
|
||||
|
||||
// 匹配邮箱
|
||||
emailStr = `[\w.-]+@[\w_-]+\w{1,}[\.\w-]+`
|
||||
|
||||
// 匹配IP4
|
||||
ip4Str = `((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
|
||||
ip6Str = `(([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
|
||||
ipStr = "(" + ip4Str + ")|(" + ip6Str + ")"
|
||||
|
||||
// 匹配域名
|
||||
domainStr = `[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
|
||||
urlStr = `((https|http|ftp|rtsp|mms)?://)?` + // 协议
|
||||
`(([0-9a-zA-Z]+:)?[0-9a-zA-Z_-]+@)?` + // pwd:user@
|
||||
"(" + ipStr + "|(" + domainStr + "))" + // IP或域名
|
||||
`(:\d{1,4})?` + // 端口
|
||||
`(/+[a-zA-Z0-9][a-zA-Z0-9_.-]*/*)*` + // path
|
||||
`(\?([a-zA-Z0-9_-]+(=[a-zA-Z0-9_-]*)*)*)*` // query
|
||||
)
|
||||
|
||||
func regexpCompile(str string) *regexp.Regexp {
|
||||
return regexp.MustCompile("^" + str + "$")
|
||||
}
|
||||
|
||||
var (
|
||||
email = regexpCompile(emailStr)
|
||||
ip4 = regexpCompile(ip4Str)
|
||||
ip6 = regexpCompile(ip6Str)
|
||||
ip = regexpCompile(ipStr)
|
||||
url = regexpCompile(urlStr)
|
||||
cnPhone = regexpCompile(cnPhoneStr)
|
||||
cnMobile = regexpCompile(cnMobileStr)
|
||||
)
|
||||
|
||||
// 判断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
|
||||
}
|
||||
}
|
||||
|
||||
// 验证中国大陆的电话号码。支持如下格式:
|
||||
// 0578-12345678-1234
|
||||
// 057812345678-1234
|
||||
// 若存在分机号,则分机号的连接符不能省略。
|
||||
func IsCnPhone(val interface{}) bool {
|
||||
return isMatch(cnPhone, val)
|
||||
}
|
||||
|
||||
// 验证中国大陆的手机号码
|
||||
func IsCnMobile(val interface{}) bool {
|
||||
return isMatch(cnMobile, val)
|
||||
}
|
||||
|
||||
// 验证一个值是否标准的URL格式。支持IP和域名等格式
|
||||
func IsURL(val interface{}) bool {
|
||||
return isMatch(url, val)
|
||||
}
|
||||
|
||||
// 验证一个值是否为IP,可验证IP4和IP6
|
||||
func IsIP(val interface{}) bool {
|
||||
return isMatch(ip, val)
|
||||
}
|
||||
|
||||
// 验证一个值是否为IP6
|
||||
func IsIP6(val interface{}) bool {
|
||||
return isMatch(ip6, val)
|
||||
}
|
||||
|
||||
// 验证一个值是滞为IP4
|
||||
func IsIP4(val interface{}) bool {
|
||||
return isMatch(ip4, val)
|
||||
}
|
||||
|
||||
// 验证一个值是否匹配一个邮箱。
|
||||
func IsEmail(val interface{}) bool {
|
||||
return isMatch(email, val)
|
||||
}
|
||||
Generated
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
// Copyright 2014 by caixw, All rights reserved.
|
||||
// Use of this source code is governed by a MIT
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package validator
|
||||
|
||||
import (
|
||||
"github.com/caixw/lib.go/assert"
|
||||
)
|
||||
|
||||
// 判断一个[]byte变量是否可以转换成数值。
|
||||
func IsNumberBytes(bs []byte) bool {
|
||||
// 首位字符可以是[0-9.+-]
|
||||
b := bs[0]
|
||||
if (b < '0' && b > '9') && b != '+' && b != '-' && b != '.' {
|
||||
return false
|
||||
}
|
||||
|
||||
hasDot := (b == '.')
|
||||
for _, b = range bs[1:] {
|
||||
if (b < '0' || b > '9') && b != '.' {
|
||||
return false
|
||||
}
|
||||
|
||||
if b == '.' {
|
||||
if hasDot { // 多个小数点
|
||||
return false
|
||||
}
|
||||
hasDot = true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 判断一个值是否可转换为数值。不支持全角数值的判断。
|
||||
// 允许带一个小数点及起始的正负号,但不允许千位分隔符什么的。
|
||||
func IsNumber(val interface{}) bool {
|
||||
switch v := val.(type) {
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
|
||||
return true
|
||||
case []byte:
|
||||
return IsNumberBytes(v)
|
||||
case string:
|
||||
return IsNumberBytes([]byte(v))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为空值。
|
||||
// 具体参照githbu.com/caixw/lib.go/assert.IsEmtpy()
|
||||
func IsEmpty(val interface{}) bool {
|
||||
return assert.IsEmpty(val)
|
||||
}
|
||||
|
||||
// 判断是否为Nil。
|
||||
// 具体参照githbu.com/caixw/lib.go/assert.IsNil()
|
||||
func IsNil(val interface{}) bool {
|
||||
return assert.IsNil(val)
|
||||
}
|
||||
Reference in New Issue
Block a user