emahiro/b.log

Drastically Repeat Yourself !!!!

strings package を使って簡単なメールのフォーマットチェックをする

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 の数を考えると

  1. ema@ の時 -> Index の値が len("ema@") - 1 に一致する。
  2. @emahiro.com のとき -> Index の値が 0
  3. 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 使う方が良いっぽいです。