Skip to content

Commit

Permalink
perf(validator): CNMobile 不再采用正则表达式验证
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Jan 29, 2024
1 parent 7525731 commit 0b32b36
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 40 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
11 changes: 11 additions & 0 deletions validator/bench_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
}
1 change: 1 addition & 0 deletions validator/number.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package validator

// TODO(go1.21): 改为 cmd.Ordered
type Number interface {
float32 | float64 |
~int | ~int8 | ~int16 | ~int32 | ~int64 |
Expand Down
18 changes: 2 additions & 16 deletions validator/regexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 + "$") }

Expand All @@ -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 {
Expand Down
17 changes: 0 additions & 17 deletions validator/regexp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
35 changes: 35 additions & 0 deletions validator/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
17 changes: 17 additions & 0 deletions validator/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
2 changes: 1 addition & 1 deletion validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit 0b32b36

Please sign in to comment.