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

Go:
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

plaintext:
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

Go:
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
}