Here are 4 way to Check if a String Contains Only Letter and Digits in Go, which use regexp
, strings.ContainsRune
, unicode
and Ascii
.
benchmark
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package bench
import (
"os"
"regexp"
"strings"
"testing"
"unicode"
)
var s = "AAAAAaaaa1234871qa"
func TestMain(m *testing.M) {
var s2 = "AAAAAaaaa1234871qa_="
if !byRegexp(s) {
panic("xxx")
}
if byRegexp(s2) {
panic("xxx2")
}
if !byRegexp2(s) {
panic("xxx")
}
if byRegexp2(s2) {
panic("xxx2")
}
if !byContainsRune(s) {
panic("xxx")
}
if byContainsRune(s2) {
panic("xxx2")
}
if !byUnicode(s) {
panic("xxx")
}
if byUnicode(s2) {
panic("xxx2")
}
if !byAscii(s) {
panic("xxx")
}
if byAscii(s2) {
panic("xxx2")
}
os.Exit(m.Run())
}
var reg2 = regexp.MustCompile("^[a-zA-Z0-9]+$")
func byRegexp(s string) bool {
reg := regexp.MustCompile("^[a-zA-Z0-9]+$")
return reg.MatchString(s)
}
func byRegexp2(s string) bool {
return reg2.MatchString(s)
}
func byContainsRune(s string) bool {
for _, ch := range s {
if !strings.ContainsRune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", ch) {
return false
}
}
return true
}
func byUnicode(s string) bool {
for _, ch := range s {
if !unicode.IsLetter(ch) && !unicode.IsDigit(ch) {
return false
}
}
return true
}
func byAscii(s string) bool {
// 0-9, A-Z, a-z
// 48-57, 65-90, 97-122
for _, c := range s {
if (c < 48 || c > 57) && (c < 65 || c > 90) && (c < 97 || c > 122) {
return false
}
}
return true
}
func BenchmarkRegexp(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StartTimer()
byRegexp(s)
}
}
func BenchmarkRegexp2(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StartTimer()
byRegexp2(s)
}
}
func BenchmarkContainsRune(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StartTimer()
byContainsRune(s)
}
}
func BenchmarkUnicode(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StartTimer()
byUnicode(s)
}
}
func BenchmarkAscii(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StartTimer()
byAscii(s)
}
}
Output
1
2
3
4
5
6
$ go test check_string_test.go -bench=. -benchmem
BenchmarkRegexp-8 344239 3142 ns/op 2520 B/op 38 allocs/op
BenchmarkRegexp2-8 3157544 376.5 ns/op 0 B/op 0 allocs/op
BenchmarkContainsRune-8 9388800 121.2 ns/op 0 B/op 0 allocs/op
BenchmarkUnicode-8 29575885 39.86 ns/op 0 B/op 0 allocs/op
BenchmarkAscii-8 53460421 22.20 ns/op 0 B/op 0 allocs/op
The best
1
2
3
4
5
6
7
8
9
10
func byAscii(s string) bool {
// 0-9, A-Z, a-z
// 48-57, 65-90, 97-122
for _, c := range s {
if (c < 48 || c > 57) && (c < 65 || c > 90) && (c < 97 || c > 122) {
return false
}
}
return true
}