├── go.mod ├── gb11643.go ├── isbn_test.go ├── .editorconfig ├── .gitignore ├── isbn.go ├── luhn ├── luhn_test.go └── luhn.go ├── go.sum ├── gb11643_test.go ├── gb11643 └── gb11643.go ├── .github └── workflows │ └── go.yml ├── regexp.go ├── LICENSE ├── is.go ├── README.md ├── regexp_test.go └── is_test.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/issue9/is 2 | 3 | require ( 4 | github.com/issue9/assert v1.4.1 5 | github.com/issue9/validation v0.2.0 6 | ) 7 | 8 | go 1.13 9 | -------------------------------------------------------------------------------- /gb11643.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import "github.com/issue9/validation/is" 6 | 7 | // GB11643 判断一个身份证是否符合 gb11643 标准 8 | // 9 | // 若是 15 位则当作一代身份证,仅简单地判断各位是否都是数字; 10 | // 若是 18 位则当作二代身份证,会计算校验位是否正确; 11 | // 其它位数都返回 false。 12 | func GB11643(val interface{}) bool { 13 | return is.GB11643(val) 14 | } 15 | -------------------------------------------------------------------------------- /isbn_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/issue9/assert" 9 | ) 10 | 11 | func TestISBN(t *testing.T) { 12 | a := assert.New(t) 13 | 14 | a.True(ISBN("1-919876-03-0")) 15 | a.True(ISBN("0-471-00084-1")) 16 | a.True(ISBN("978-7-301-04815-3")) 17 | a.True(ISBN("978-986-181-728-6")) 18 | } 19 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | 12 | # html 13 | [*.{htm,html,js,css}] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | # 配置文件 18 | [*.{yml,yaml,json}] 19 | indent_style = space 20 | indent_size = 2 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | # vim 27 | *.swp 28 | 29 | # osx 30 | .DS_Store 31 | 32 | .vscode 33 | -------------------------------------------------------------------------------- /isbn.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import ( 6 | "github.com/issue9/validation/is" 7 | ) 8 | 9 | // 有关 ISBN 的算法及其它相关内容,可参照http://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E6%A0%87%E5%87%86%E4%B9%A6%E5%8F%B7 10 | 11 | // ISBN 判断是否为合法的 ISBN 串号。可以同时判断 ISBN10 和 ISBN13 12 | func ISBN(val interface{}) bool { 13 | return is.ISBN(val) 14 | } 15 | 16 | // ISBN10 判断是否为合法的 ISBN10 17 | func ISBN10(val []byte) bool { 18 | return is.ISBN10(val) 19 | } 20 | 21 | // ISBN13 判断是否为合法的 ISBN13 22 | func ISBN13(val []byte) bool { 23 | return is.ISBN13(val) 24 | } 25 | -------------------------------------------------------------------------------- /luhn/luhn_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package luhn 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/issue9/assert" 9 | ) 10 | 11 | func TestString(t *testing.T) { 12 | a := assert.New(t) 13 | 14 | a.True(ValidString("6259650871772098")) 15 | a.True(ValidString("79927398713")) 16 | a.False(ValidString("79927398710")) 17 | } 18 | 19 | func TestGenerateWithPrefix(t *testing.T) { 20 | a := assert.New(t) 21 | 22 | a.Equal("6259650871772098", string(GenerateWithPrefix([]byte("625965087177209")))) 23 | a.True(Valid(GenerateWithPrefix([]byte("625965087177209")))) 24 | } 25 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/issue9/assert v1.4.1 h1:gUtOpMTeaE4JTe9kACma5foOHBvVt1p5XTFrULDwdXI= 2 | github.com/issue9/assert v1.4.1/go.mod h1:Yktk83hAVl1SPSYtd9kjhBizuiBIqUQyj+D5SE2yjVY= 3 | github.com/issue9/sliceutil v0.6.0/go.mod h1:FUxZQC4oEw6V46afC+JOdCjOv84BA6WBNQRYGS9V4Dg= 4 | github.com/issue9/validation v0.2.0 h1:UQ747kk0cGHQWpL6cuUpf8ubeI6e8ZgPa94TZC0O42w= 5 | github.com/issue9/validation v0.2.0/go.mod h1:My0wEa+KUEiKN+1IaFEb0eqyr8KhMBPd61qV9DtBVhI= 6 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 7 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 8 | -------------------------------------------------------------------------------- /luhn/luhn.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | // Package luhn 模 10 校验算法 4 | // 5 | // https://en.wikipedia.org/wiki/Luhn_algorithm 6 | // 7 | // 1. 从右往左,偶数位数字乘以 2,如果是两位数,将其个数数和十位数相加; 8 | // 2. 将以上的所有数值相加得到值 n1; 9 | // 3. 从右往左,奇数位的数值加相加午到值 n2; 10 | // 4. (n1+n2) % 10 如果值为 0,表示正确。 11 | package luhn 12 | 13 | import "github.com/issue9/validation/is/luhn" 14 | 15 | // Valid 传入 []byte 验证是否正确 16 | func Valid(v []byte) bool { 17 | return luhn.IsValid(v) 18 | } 19 | 20 | // ValidString 传入 string 验证是否正确 21 | func ValidString(v string) bool { 22 | return Valid([]byte(v)) 23 | } 24 | 25 | // GenerateWithPrefix 给定前缀,添加最后一位校验位 26 | func GenerateWithPrefix(prefix []byte) []byte { 27 | return luhn.GenerateWithPrefix(prefix) 28 | } 29 | -------------------------------------------------------------------------------- /gb11643_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/issue9/assert" 9 | ) 10 | 11 | func TestGB11643(t *testing.T) { 12 | a := assert.New(t) 13 | 14 | // 网上扒来的身份证,不与现实中的对应。 15 | a.True(GB11643("350303199002033073")) 16 | a.True(GB11643("350303900203307")) 17 | a.True(GB11643("331122197905116239")) 18 | a.True(GB11643("513330199111066159")) 19 | a.True(GB11643("33050219880702447x")) 20 | a.True(GB11643("33050219880702447X")) 21 | a.True(GB11643("330502880702447")) 22 | 23 | a.False(GB11643("111111111111111111")) 24 | a.False(GB11643("330502198807024471")) // 最后一位不正确 25 | a.False(GB11643("33050288070244")) // 14位 26 | a.False(GB11643("3305028807024411")) // 16位 27 | } 28 | -------------------------------------------------------------------------------- /gb11643/gb11643.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | // Package gb11643 解析身分证详情 4 | package gb11643 5 | 6 | import ( 7 | "github.com/issue9/validation/is/gb11643" 8 | ) 9 | 10 | // 我国现行的身份证号码有两种标准:GB11643-1989、GB11643-1999: 11 | // 12 | // GB11643-1989为一代身份证,从左至右分别为: 13 | // ------------------------------------------------------------ 14 | // | 6位行政区域代码 | 6位出生年日期(不含世纪数)| 3位顺序码 | 15 | // ------------------------------------------------------------ 16 | // 17 | // GB11643-1999为二代身份证,从左至右分别为: 18 | // ------------------------------------------------------------ 19 | // | 6位行政区域代码 | 8位出生日期 | 3位顺序码 | 1位检验码 | 20 | // ------------------------------------------------------------ 21 | 22 | const layout = "20060102" 23 | 24 | // GB11643 身份证信息 25 | type GB11643 = gb11643.GB11643 26 | 27 | // Parse 分析身份证信息 28 | // 29 | // 不作正确性检测,如有需求,请使用 is.GB11643 30 | func Parse(bs string) (*GB11643, error) { 31 | return gb11643.Parse(bs) 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | 6 | test: 7 | name: Test 8 | runs-on: ${{ matrix.os }} 9 | 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macOS-latest, windows-latest] 13 | go: ['1.14.x', '1.13.x'] 14 | 15 | steps: 16 | 17 | - name: Check out code into the Go module directory 18 | uses: actions/checkout@v1 19 | 20 | - name: Set up Go ${{ matrix.go }} 21 | uses: actions/setup-go@v1 22 | with: 23 | go-version: ${{ matrix.go }} 24 | id: go 25 | 26 | - name: Vet 27 | run: go vet -v ./... 28 | 29 | - name: Test 30 | run: go test -v -coverprofile='coverage.txt' -covermode=atomic ./... 31 | 32 | - name: Upload Coverage report 33 | uses: codecov/codecov-action@v1 34 | with: 35 | token: ${{secrets.CODECOV_TOKEN}} 36 | file: ./coverage.txt 37 | -------------------------------------------------------------------------------- /regexp.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import "github.com/issue9/validation/is" 6 | 7 | // CNPhone 验证中国大陆的电话号码 8 | // 9 | // 支持如下格式: 10 | // 0578-12345678-1234 11 | // 057812345678-1234 12 | // 若存在分机号,则分机号的连接符不能省略。 13 | func CNPhone(val interface{}) bool { 14 | return is.CNPhone(val) 15 | } 16 | 17 | // CNMobile 验证中国大陆的手机号码 18 | func CNMobile(val interface{}) bool { 19 | return is.CNMobile(val) 20 | } 21 | 22 | // CNTel 验证手机和电话类型 23 | func CNTel(val interface{}) bool { 24 | return is.CNTel(val) 25 | } 26 | 27 | // URL 验证一个值是否标准的URL格式 28 | // 29 | // 支持 IP 和域名等格式 30 | func URL(val interface{}) bool { 31 | return is.URL(val) 32 | } 33 | 34 | // IP 验证一个值是否为 IP 35 | // 36 | // 可验证 IP4 和 IP6 37 | func IP(val interface{}) bool { 38 | return is.IP(val) 39 | } 40 | 41 | // IP6 验证一个值是否为 IP6 42 | func IP6(val interface{}) bool { 43 | return is.IP6(val) 44 | } 45 | 46 | // IP4 验证一个值是滞为 IP4 47 | func IP4(val interface{}) bool { 48 | return is.IP4(val) 49 | } 50 | 51 | // Email 验证一个值是否匹配一个邮箱 52 | func Email(val interface{}) bool { 53 | return is.Email(val) 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 caixw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /is.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | // Package is 包提供了一系列的判断函数 4 | package is 5 | 6 | import ( 7 | "github.com/issue9/validation/is" 8 | ) 9 | 10 | // Number 判断一个值是否可转换为数值 11 | // 12 | // NOTE: 不支持全角数值的判断 13 | func Number(val interface{}) bool { 14 | return is.Number(val) 15 | } 16 | 17 | // Nil 是否为 nil 18 | // 19 | // 有类型但无具体值的也将返回 true, 20 | // 当特定类型的变量,已经声明,但还未赋值时,也将返回 true 21 | func Nil(val interface{}) bool { 22 | return is.Nil(val) 23 | } 24 | 25 | // Empty 判断当前是否为空或是零值 26 | // 27 | // ptr 表示当 val 是指针时,是否分析指向的值。 28 | // 29 | // 若是容器类型,长度为 0 也将返回 true, 30 | // 但是 []string{""}空数组里套一个空字符串,不会被判断为空。 31 | func Empty(val interface{}, ptr bool) bool { 32 | return is.Empty(val, ptr) 33 | } 34 | 35 | // Zero 判断当前是否为空或是零值 36 | // 37 | // ptr 表示当 val 是指针时,是否分析指向的值。 38 | // 在 reflect.Value.IsZero 的基础上对特写类型作为特殊处理,比如 time.IsZero() 39 | func Zero(val interface{}, ptr bool) bool { 40 | return is.Zero(val, ptr) 41 | } 42 | 43 | // HexColor 判断一个字符串是否为合法的 16 进制颜色表示法 44 | func HexColor(val interface{}) bool { 45 | return is.HexColor(val) 46 | } 47 | 48 | // BankCard 是否为正确的银行卡号 49 | func BankCard(val interface{}) bool { 50 | return is.BankCard(val) 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | is 2 | [![Go](https://github.com/issue9/is/workflows/Go/badge.svg)](https://github.com/issue9/is/actions?query=workflow%3AGo) 3 | [![license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://opensource.org/licenses/MIT) 4 | [![codecov](https://codecov.io/gh/issue9/is/branch/master/graph/badge.svg)](https://codecov.io/gh/issue9/is) 5 | ====== 6 | 7 | **不再更新,相关函数可采用 下的内容** 8 | 9 | 一些常用的验证函数: 10 | 11 | ```go 12 | // 判断是否为数值 13 | is.Number("123") 14 | 15 | // 判断是否为ISBN序列号 16 | is.ISBN("1-919876-03-0") 17 | 18 | // 身份证验证 19 | is.GB11643("33232333211233432") 20 | 21 | // 银行卡验证 22 | is.BankCard("33232123234") 23 | ``` 24 | 25 | 安装 26 | ---- 27 | 28 | ```shell 29 | go get github.com/issue9/is 30 | ``` 31 | 32 | 文档 33 | ---- 34 | 35 | [![Go Walker](https://gowalker.org/api/v1/badge)](https://gowalker.org/github.com/issue9/is) 36 | [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/issue9/is) 37 | 38 | 版权 39 | ---- 40 | 41 | 本项目采用 [MIT](https://opensource.org/licenses/MIT) 开源授权许可证,完整的授权说明可在 [LICENSE](LICENSE) 文件中找到。 42 | -------------------------------------------------------------------------------- /regexp_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/issue9/assert" 9 | ) 10 | 11 | func TestCNPhone(t *testing.T) { 12 | a := assert.New(t) 13 | 14 | a.True(CNPhone("444488888888-4444")) 15 | a.True(CNPhone("3337777777-1")) 16 | a.True(CNPhone("333-7777777-1")) 17 | a.True(CNPhone("7777777")) 18 | a.True(CNPhone("88888888")) 19 | 20 | a.False(CNPhone("333-7777777-")) // 尾部没有分机号 21 | a.False(CNPhone("22-88888888")) // 区号只有2位 22 | a.False(CNPhone("33-88888888-55555")) // 分机号超过4位 23 | } 24 | 25 | func TestCNMobile(t *testing.T) { 26 | a := assert.New(t) 27 | 28 | a.True(CNMobile("15011111111")) 29 | a.True(CNMobile("015011111111")) 30 | a.True(CNMobile("8615011111111")) 31 | a.True(CNMobile("+8615011111111")) 32 | a.True(CNMobile("+8619911111111")) 33 | 34 | a.False(CNMobile("+86150111111112")) // 尾部多个2 35 | a.False(CNMobile("50111111112")) // 开头少1 36 | a.False(CNMobile("+8650111111112")) // 开头少1 37 | a.False(CNMobile("8650111111112")) // 开头少1 38 | a.False(CNMobile("154111111112")) // 不存在的前缀154 39 | a.True(CNMobile("15411111111")) 40 | } 41 | 42 | func TestCNTel(t *testing.T) { 43 | a := assert.New(t) 44 | 45 | a.True(CNTel("444488888888-4444")) 46 | a.True(CNTel("3337777777-1")) 47 | a.True(CNTel("333-7777777-1")) 48 | a.True(CNTel("7777777")) 49 | a.True(CNTel("88888888")) 50 | a.True(CNTel("15011111111")) 51 | a.True(CNTel("015011111111")) 52 | a.True(CNTel("8615011111111")) 53 | a.True(CNTel("+8615011111111")) 54 | } 55 | 56 | func TestURL(t *testing.T) { 57 | a := assert.New(t) 58 | 59 | a.True(URL("www.example.com")) 60 | a.True(URL("http://www.example.com")) 61 | a.True(URL([]byte("http://example.com"))) 62 | a.True(URL("http://www.example.com/")) 63 | a.True(URL("http://www.example.com/path/?a=b")) 64 | a.True(URL("https://www.example.com:88/path1/path2")) 65 | a.True(URL("ftp://pwd:user@www.example.com/index.go?a=b")) 66 | a.True(URL([]byte("ftp://pwd:user@www.example.com/index.go?a=b"))) 67 | a.True(URL("pwd:user@www.example.com/path/")) 68 | a.True(URL("pwd:user@www.example.com:80/path/")) 69 | a.True(URL("https://127.0.0.1/path/")) 70 | a.True(URL("https://fe80:0:0:0:204:61ff:fe9d:f156/path/")) 71 | a.True(URL("https://127.0.0.1/path//index.go?arg1=val1&arg2=val/2")) 72 | a.True(URL("https://::1/path/index.go?arg1=val1")) 73 | 74 | a.False(URL("https://[::1]:80/path/")) 75 | a.False(URL("https://298.1.1.1/path/index.go?arg1=val1")) 76 | a.False(URL("https://~.example.com/path/index.go?arg1=val1")) 77 | } 78 | 79 | func TestIP(t *testing.T) { 80 | a := assert.New(t) 81 | 82 | a.True(IP("fe80:0000:0000:0000:0204:61ff:fe9d:f156")) 83 | a.True(IP("fe80:0:0:0:204:61ff:fe9d:f156")) 84 | a.True(IP("0.0.0.0")) 85 | a.True(IP("255.255.255.255")) 86 | a.True(IP("255.0.3.255")) 87 | 88 | a.False(IP("255.0:3.255")) 89 | a.False(IP("275.0.3.255")) 90 | } 91 | 92 | func TestIP6(t *testing.T) { 93 | a := assert.New(t) 94 | 95 | a.True(IP6("fe80:0000:0000:0000:0204:61ff:fe9d:f156")) // full form of IPv6 96 | a.True(IP6("fe80:0:0:0:204:61ff:fe9d:f156")) // drop leading zeroes 97 | a.True(IP6("fe80::204:61ff:fe9d:f156")) // collapse multiple zeroes to :: in the IPv6 address 98 | a.True(IP6("fe80:0000:0000:0000:0204:61ff:254.157.241.86")) // IPv4 dotted quad at the end 99 | a.True(IP6("fe80:0:0:0:0204:61ff:254.157.241.86")) // drop leading zeroes, IPv4 dotted quad at the end 100 | a.True(IP6("fe80::204:61ff:254.157.241.86")) // dotted quad at the end, multiple zeroes collapsed 101 | a.True(IP6("::1")) // localhost 102 | a.True(IP6("fe80::")) // link-local prefix 103 | a.True(IP6("2001::")) // global unicast prefix 104 | } 105 | 106 | func TestIP4(t *testing.T) { 107 | a := assert.New(t) 108 | 109 | a.True(IP4("0.0.0.0")) 110 | a.True(IP4("255.255.255.255")) 111 | a.True(IP4("255.0.3.255")) 112 | a.True(IP4("127.010.0.1")) 113 | a.True(IP4("027.01.0.1")) 114 | 115 | a.False(IP4("1127.01.0.1")) 116 | } 117 | 118 | func TestEmail(t *testing.T) { 119 | a := assert.New(t) 120 | 121 | a.True(Email("email@email.com")) 122 | a.True(Email("em2il@email.com.cn")) 123 | a.True(Email("12345@qq.com")) 124 | a.True(Email("email.test@email.com")) 125 | a.True(Email("email.test@email123.com")) 126 | a.True(Email("em2il@email")) 127 | 128 | // 2个@ 129 | a.False(Email("em@2l@email.com")) 130 | // 没有@ 131 | a.False(Email("email2email.com.cn")) 132 | } 133 | -------------------------------------------------------------------------------- /is_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package is 4 | 5 | import ( 6 | "bytes" 7 | "math" 8 | "testing" 9 | "time" 10 | 11 | "github.com/issue9/assert" 12 | ) 13 | 14 | func TestNumber(t *testing.T) { 15 | a := assert.New(t) 16 | 17 | a.True(Number("123")) 18 | a.True(Number("+123")) 19 | a.True(Number("-123")) 20 | a.True(Number(".123")) 21 | a.True(Number("12.3")) 22 | a.True(Number("+12.3")) 23 | a.True(Number("-123.")) 24 | 25 | a.False(Number("1-23")) 26 | a.False(Number("+abc")) 27 | a.False(Number(".12.3")) 28 | a.False(Number("123")) // 全角 29 | 30 | a.True(Number(123)) 31 | a.True(Number(123.1)) 32 | a.True(Number(0)) 33 | a.True(Number(math.Inf(1))) 34 | a.True(Number(math.Inf(-1))) 35 | a.True(Number([]rune("123.3"))) 36 | a.True(Number([]byte("123.3"))) 37 | } 38 | 39 | func TestNil(t *testing.T) { 40 | a := assert.New(t) 41 | 42 | a.True(Nil(nil)) 43 | 44 | var x interface{} 45 | a.True(Nil(x)) 46 | 47 | var y *bytes.Buffer 48 | a.True(Nil(y)) 49 | 50 | a.False(Nil(0)) 51 | 52 | x = 5 53 | a.False(Nil(x)) 54 | 55 | y = new(bytes.Buffer) 56 | a.False(Nil(y)) 57 | } 58 | 59 | func TestEmpty(t *testing.T) { 60 | a := assert.New(t) 61 | 62 | a.True(Empty(0, false)) 63 | a.True(Empty(nil, false)) 64 | a.True(Empty(nil, true)) 65 | a.True(Empty(0.0, false)) 66 | a.False(Empty(-0.0001, true)) 67 | 68 | var i interface{} 69 | a.True(Empty(i, false)) 70 | a.True(Empty(i, true)) 71 | a.False(Empty(&i, false)) 72 | a.True(Empty(&i, true)) 73 | 74 | i = []string{} 75 | a.True(Empty(i, false)) 76 | a.True(Empty(i, true)) 77 | a.False(Empty(&i, false)) 78 | a.True(Empty(&i, true)) 79 | 80 | var x []string 81 | a.True(Empty(x, false)) 82 | a.True(Empty(x, true)) 83 | a.False(Empty(&x, false)) 84 | a.True(Empty(&x, true)) 85 | 86 | x = []string{""} 87 | a.False(Empty(x, false)) 88 | a.False(Empty(x, true)) 89 | 90 | var ii interface{} = []string{} 91 | a.True(Empty(ii, false)) 92 | a.True(Empty(ii, true)) 93 | a.False(Empty(&ii, false)) 94 | a.True(Empty(&ii, true)) 95 | 96 | var m map[string]string 97 | a.True(Empty(m, false)) 98 | a.True(Empty(m, true)) 99 | a.False(Empty(&m, false)) 100 | a.True(Empty(&m, true)) 101 | 102 | m = map[string]string{} 103 | a.True(Empty(m, false)) 104 | a.True(Empty(m, true)) 105 | a.False(Empty(&m, false)) 106 | a.True(Empty(&m, true)) 107 | 108 | i = m 109 | a.True(Empty(m, false)) 110 | a.True(Empty(m, true)) 111 | a.False(Empty(&m, false)) 112 | a.True(Empty(&m, true)) 113 | 114 | a.True(Empty(time.Time{}, false)) 115 | a.True(Empty(time.Time{}, true)) 116 | a.False(Empty(&time.Time{}, false)) 117 | a.True(Empty(&time.Time{}, true)) 118 | a.False(Empty(time.Now(), false)) 119 | a.False(Empty(time.Now(), true)) 120 | 121 | type obj struct{ Int int } 122 | a.True(Empty(obj{Int: 0}, false)) 123 | a.False(Empty(&obj{Int: 0}, false)) 124 | a.True(Empty(&obj{Int: 0}, true)) 125 | a.False(Empty(obj{Int: 1}, false)) 126 | } 127 | 128 | func TestZero(t *testing.T) { 129 | a := assert.New(t) 130 | 131 | a.True(Zero(0, false)) 132 | a.True(Zero(nil, false)) 133 | a.True(Zero(nil, true)) 134 | a.True(Zero(0.0, false)) 135 | a.False(Zero(-0.0001, true)) 136 | 137 | var i interface{} 138 | a.True(Zero(i, false)) 139 | a.True(Zero(i, true)) 140 | a.False(Zero(&i, false)) 141 | a.True(Zero(&i, true)) 142 | 143 | i = []string{} 144 | a.False(Zero(i, false)) 145 | a.False(Zero(i, true)) 146 | a.False(Zero(&i, false)) 147 | a.False(Zero(&i, true)) 148 | 149 | var x []string 150 | a.True(Zero(x, false)) 151 | a.True(Zero(x, true)) 152 | a.False(Zero(&x, false)) 153 | a.True(Zero(&x, true)) 154 | 155 | x = []string{""} 156 | a.False(Zero(x, false)) 157 | a.False(Zero(x, true)) 158 | 159 | var ii interface{} = []string{} 160 | a.False(Zero(ii, false)) 161 | a.False(Zero(ii, true)) 162 | a.False(Zero(&ii, false)) 163 | a.False(Zero(&ii, true)) 164 | 165 | var m map[string]string 166 | a.True(Zero(m, false)) 167 | a.True(Zero(m, true)) 168 | a.False(Zero(&m, false)) 169 | a.True(Zero(&m, true)) 170 | 171 | m = map[string]string{} 172 | a.False(Zero(m, false)) 173 | a.False(Zero(m, true)) 174 | a.False(Zero(&m, false)) 175 | a.False(Zero(&m, true)) 176 | 177 | i = m 178 | a.False(Zero(m, false)) 179 | a.False(Zero(m, true)) 180 | a.False(Zero(&m, false)) 181 | a.False(Zero(&m, true)) 182 | 183 | a.True(Zero(time.Time{}, false)) 184 | a.True(Zero(time.Time{}, true)) 185 | a.False(Zero(&time.Time{}, false)) 186 | a.True(Zero(&time.Time{}, true)) 187 | a.False(Zero(time.Now(), false)) 188 | a.False(Zero(time.Now(), true)) 189 | 190 | type obj struct{ Int int } 191 | a.True(Zero(obj{Int: 0}, false)) 192 | a.False(Zero(&obj{Int: 0}, false)) 193 | a.True(Zero(&obj{Int: 0}, true)) 194 | a.False(Zero(obj{Int: 1}, false)) 195 | } 196 | 197 | func TestHexColor(t *testing.T) { 198 | a := assert.New(t) 199 | 200 | a.True(HexColor("#123")) 201 | a.True(HexColor("#fff")) 202 | a.True(HexColor("#f0f0f0")) 203 | a.True(HexColor("#fafafa")) 204 | a.True(HexColor("#224422")) 205 | 206 | a.False(HexColor("#2244")) 207 | a.False(HexColor("#hhh")) 208 | a.False(HexColor("#asdf")) 209 | a.False(HexColor("#ffff")) 210 | } 211 | --------------------------------------------------------------------------------