Overview
タイトルの通りです。Go の strings パッケージを使って簡単なメールアドレスのフォーマットチェックをします。
Go の正規表現は重たい(Go に限った話ではないですが)処理なので何かの文字列の検査をするときは strings package を使う方がパフォーマンスにも優しいことが多いです(ちょっとめんどくさいですが)
strings.Split を使う
@
ドメインでぶった斬るパターンですね。ema@emahiro.com
みたいな文字列を考えると Split した結果の slice の長さは 2 なので ema@
や @emahiro.com
みたいなケースをカバーして以下のようなサンプルをかけます。
func StringSplit(email string) error { splt := strings.Split(email, "@") err := errors.New("invalid format") if len(splt) != 2 { return err } if len(splt[:len(splt)-1]) == 0 && len(splt[len(splt)-1:]) == 1 { return err } if len(splt[:len(splt)-1]) == 1 && len(splt[len(splt)-1]) == 0 { return err } return nil }
strings.Index を使う
特定の文字までの位置を返してくれる Index も使えます。ここでは @
までの Index の数を考えると
ema@
の時 -> Index の値がlen("ema@") - 1
に一致する。@emahiro.com
のとき -> Index の値が0
。ema
のとき -> Index は-1
。
func StringIndex(email string) error { switch strings.Index(email, "@") { case -1, 0, len(email) - 1: return errors.New("invalid format") } return nil }
余談: パフォーマンスを見てみる
strings.Split
を使っても strings.Index
を使っても検査は可能ですが試しにパフォーマンスを見てみます。
package main import ( "strings" "testing" ) func BenchmarkStringIndex(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = strings.Index("ema@emahiro.com", "@") } } func BenchmarkStringSplit(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { _ = strings.Split("ema@emahiro.com", "@") } }
出力結果は以下
go test -v -bench=. -benchmem goos: darwin goarch: amd64 pkg: emahiro.dev/go-bench-sandbox cpu: VirtualApple @ 2.50GHz BenchmarkStringIndex BenchmarkStringIndex-10 153256222 7.003 ns/op 0 B/op 0 allocs/op BenchmarkStringSplit BenchmarkStringSplit-10 17826536 65.38 ns/op 32 B/op 1 allocs/op PASS ok
Index の方がパフォーマンスが良いですね。
まとめ
文字列チェックするときは Index 使う方が良いっぽいです。