In Go, write a simple function. For example,
package main
import (
"fmt"
)
func isStandard(s string) bool {
for i := 0; i < len(s); i++ {
switch b := s[i]; {
case b >= 'a' && b <= 'z':
continue
case b >= 'A' && b <= 'Z':
continue
case b >= '0' && b <= '9':
continue
default:
return false
}
}
return true
}
func main() {
fmt.Println(isStandard(`ABCabc123`))
fmt.Println(isStandard(`#}{&*"(£)`))
}
Playground: https://play.golang.org/p/Y2KjDcHSupH
Output:
true
false
The Go Programming Language Specification
Switch statements
"Switch" statements provide multi-way execution. An expression or type
specifier is compared to the "cases" inside the "switch" to determine
which branch to execute.
Expression switches
In an expression switch, the switch expression is evaluated and the
case expressions, which need not be constants, are evaluated
left-to-right and top-to-bottom; the first one that equals the switch
expression triggers execution of the statements of the associated
case; the other cases are skipped. If no case matches and there is a
"default" case, its statements are executed. There can be at most one
default case and it may appear anywhere in the "switch" statement.
The switch expression may be preceded by a simple statement, which
executes before the expression is evaluated.
Fallthrough statements
A "fallthrough" statement transfers control to the first statement of
the next case clause in an expression "switch" statement. It may be
used only as the final non-empty statement in such a clause.
switch b := s[i]; {
// ...
}
is equivalent to
switch b := s[i]; true {
// ...
}
is equivalent to
{
b := s[i]
switch true {
// ...
}
}
The simple statement b := s[i]
declares b
to be a switch { }
statement block local variable.
The case expresions are evaluated and compared to true
. If none are true, the default
is taken.
Go, unlike C, requires explicit fallthrough
.
ASCII is a subset of Unicode UTF-8. Since the standard characters are all ASCII, we can simply compare bytes.
Here is a simple benchmark.
Output:
$ go test standard_test.go -bench=. -benchmem
BenchmarkPeterSO-8 200000000 8.10 ns/op 0 B/op 0 allocs/op
BenchmarkJubobs-8 10000000 222 ns/op 0 B/op 0 allocs/op
$
standard_test.go
:
package main
import (
"regexp"
"testing"
)
func isStandard(s string) bool {
for i := 0; i < len(s); i++ {
switch b := s[i]; {
case b >= 'a' && b <= 'z':
continue
case b >= 'A' && b <= 'Z':
continue
case b >= '0' && b <= '9':
continue
default:
return false
}
}
return true
}
func BenchmarkPeterSO(b *testing.B) {
std := `ABCabc123`
for N := 0; N < b.N; N++ {
isStandard(std)
}
}
var (
whitelist = "A-Za-z0-9"
disallowed = regexp.MustCompile("[^" + whitelist + " ]+")
)
func IsValid(s string) bool {
return !disallowed.MatchString(s)
}
func BenchmarkJubobs(b *testing.B) {
std := `ABCabc123`
for N := 0; N < b.N; N++ {
IsValid(std)
}
}