From 0b32b36e10c0e11f0b897edcf26bb27d4462d729 Mon Sep 17 00:00:00 2001 From: caixw Date: Mon, 29 Jan 2024 15:11:46 +0800 Subject: [PATCH] =?UTF-8?q?perf(validator):=20CNMobile=20=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E9=87=87=E7=94=A8=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 4 ++-- go.sum | 8 ++++---- validator/bench_test.go | 11 +++++++++++ validator/number.go | 1 + validator/regexp.go | 18 ++---------------- validator/regexp_test.go | 17 ----------------- validator/string.go | 35 +++++++++++++++++++++++++++++++++++ validator/string_test.go | 17 +++++++++++++++++ validator/validator.go | 2 +- 9 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 validator/bench_test.go diff --git a/go.mod b/go.mod index bfdbcb5..de74ccf 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/issue9/filter go 1.18 require ( - github.com/issue9/assert/v3 v3.0.5 - github.com/issue9/sliceutil v0.14.0 + github.com/issue9/assert/v3 v3.1.0 + github.com/issue9/sliceutil v0.15.0 ) diff --git a/go.sum b/go.sum index eefc01d..77092e1 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ -github.com/issue9/assert/v3 v3.0.5 h1:Mlz/4v2Ph6ZDm3Fk3A1jhitH4M/2dkHeHNKe7tTZdH8= -github.com/issue9/assert/v3 v3.0.5/go.mod h1:yft/uaskRpwQTyBT3n1zRl91SR1wNlO4fLZHzOa4bdM= -github.com/issue9/sliceutil v0.14.0 h1:5jVgAW7oLxmCo9r1QrTcXNQ7g7/yjqbNnFLsI2eV/tY= -github.com/issue9/sliceutil v0.14.0/go.mod h1:n9meV7AamDhmehOBuV4GrxW3yw7O1cZmLx3Xizg1bps= +github.com/issue9/assert/v3 v3.1.0 h1:oxLFXS7QnBKI4lB31pRoYO96yErkWAJtR7iv+LNjAPg= +github.com/issue9/assert/v3 v3.1.0/go.mod h1:yft/uaskRpwQTyBT3n1zRl91SR1wNlO4fLZHzOa4bdM= +github.com/issue9/sliceutil v0.15.0 h1:E6Xnl3FY5h0ZGNzyx1VEFAfGdParaq/BkX1QQR0uFwI= +github.com/issue9/sliceutil v0.15.0/go.mod h1:n9meV7AamDhmehOBuV4GrxW3yw7O1cZmLx3Xizg1bps= diff --git a/validator/bench_test.go b/validator/bench_test.go new file mode 100644 index 0000000..7e5bf88 --- /dev/null +++ b/validator/bench_test.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +package validator + +import "testing" + +func BenchmarkCNMobile(b *testing.B) { + for i := 0; i < b.N; i++ { + CNMobile("15011111111") + } +} diff --git a/validator/number.go b/validator/number.go index 7350244..76a287e 100644 --- a/validator/number.go +++ b/validator/number.go @@ -2,6 +2,7 @@ package validator +// TODO(go1.21): 改为 cmd.Ordered type Number interface { float32 | float64 | ~int | ~int8 | ~int16 | ~int32 | ~int64 | diff --git a/validator/regexp.go b/validator/regexp.go index 44f9ad2..d6bdc02 100644 --- a/validator/regexp.go +++ b/validator/regexp.go @@ -9,20 +9,9 @@ const ( cnPhonePattern = `((\d{3,4})-?)?` + // 区号 `\d{5,10}` + // 号码,95500 等 5 位数的,7 位,8 位,以及 400 开头的 10 位数 `(-\d{1,4})?` // 分机号,分机号的连接符号不能省略。 - - // 匹配大陆手机号码 - cnMobilePattern = `(0|\+?86)?` + // 匹配 0,86,+86 - `1[2-9]{1}[0-9]{9}` // 12x-19x - - // 匹配大陆手机号或是电话号码 - cnTelPattern = "(" + cnPhonePattern + ")|(" + cnMobilePattern + ")" ) -var ( - cnPhone = regexpCompile(cnPhonePattern) - cnMobile = regexpCompile(cnMobilePattern) - cnTel = regexpCompile(cnTelPattern) -) +var cnPhone = regexpCompile(cnPhonePattern) func regexpCompile(str string) *regexp.Regexp { return regexp.MustCompile("^" + str + "$") } @@ -36,11 +25,8 @@ func regexpCompile(str string) *regexp.Regexp { return regexp.MustCompile("^" + // 若存在分机号,则分机号的连接符不能省略。 func CNPhone(val string) bool { return Match(cnPhone)(val) } -// CNMobile 验证中国大陆的手机号码 -func CNMobile(val string) bool { return Match(cnMobile)(val) } - // CNTel 验证手机和电话类型 -func CNTel(val string) bool { return Match(cnTel)(val) } +func CNTel(val string) bool { return CNMobile(val) || CNPhone(val) } // Match 为正则生成验证函数 func Match(exp *regexp.Regexp) func(string) bool { diff --git a/validator/regexp_test.go b/validator/regexp_test.go index 1e7f288..e9147cb 100644 --- a/validator/regexp_test.go +++ b/validator/regexp_test.go @@ -22,23 +22,6 @@ func TestCNPhone(t *testing.T) { a.False(CNPhone("33-88888888-55555")) // 分机号超过4位 } -func TestCNMobile(t *testing.T) { - a := assert.New(t, false) - - a.True(CNMobile("15011111111")) - a.True(CNMobile("015011111111")) - a.True(CNMobile("8615011111111")) - a.True(CNMobile("+8615011111111")) - a.True(CNMobile("+8619911111111")) - - a.False(CNMobile("+86150111111112")) // 尾部多个2 - a.False(CNMobile("50111111112")) // 开头少1 - a.False(CNMobile("+8650111111112")) // 开头少1 - a.False(CNMobile("8650111111112")) // 开头少1 - a.False(CNMobile("154111111112")) // 不存在的前缀154 - a.True(CNMobile("15411111111")) -} - func TestCNTel(t *testing.T) { a := assert.New(t, false) diff --git a/validator/string.go b/validator/string.go index 1698b4e..923a957 100644 --- a/validator/string.go +++ b/validator/string.go @@ -136,3 +136,38 @@ func Alpha(s string) bool { func EmptyOr(v func(string) bool) func(string) bool { return Or(func(s string) bool { return s == "" }, v) } + +// CNMobile 验证中国大陆的手机号码 +func CNMobile(val string) bool { + // 可选的 0,86,086,+86 + // 开头 12x-19x + + if len(val) == 0 { + return false + } + + if val[0] == '0' || val[0] == '+' { + val = val[1:] + } + + val = strings.TrimPrefix(val, "86") + + if len(val) != 11 { + return false + } + + if val[0] != '1' { + return false + } + + return isNumber(val[1:]) +} + +func isNumber(val string) bool { + for _, c := range val[1:] { + if c < '0' || c > '9' { + return false + } + } + return true +} diff --git a/validator/string_test.go b/validator/string_test.go index 0d19766..cd53d2d 100644 --- a/validator/string_test.go +++ b/validator/string_test.go @@ -105,3 +105,20 @@ func TestAlpha(t *testing.T) { a.True(Alpha("abc")) a.False(Alpha("abc12")) } + +func TestCNMobile(t *testing.T) { + a := assert.New(t, false) + + a.True(CNMobile("15011111111")) + a.True(CNMobile("015011111111")) + a.True(CNMobile("8615011111111")) + a.True(CNMobile("+8615011111111")) + a.True(CNMobile("+8619911111111")) + + a.False(CNMobile("+86150111111112")) // 尾部多个2 + a.False(CNMobile("50111111112")) // 开头少1 + a.False(CNMobile("+8650111111112")) // 开头少1 + a.False(CNMobile("8650111111112")) // 开头少1 + a.False(CNMobile("154111111112")) // 不存在的前缀154 + a.True(CNMobile("15411111111")) +} diff --git a/validator/validator.go b/validator/validator.go index 4ab5bcf..272488a 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -2,7 +2,7 @@ // Package validator 符合 [web.filter] 的验证器 // -// [web.filter]: https://pkg.go.dev/github.com/issue9/web/filter +// [web.filter]: https://pkg.go.dev/github.com/issue9/web#Filter package validator import "reflect"