パフォーマンスのヒント
コンパイル済みregexpを再利用します
「パフォーマンスのヒント」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
コンパイルにはコストがかかる
パターン文字列を使用可能な正規表現に変換するには処理が必要です。呼び出すたびに実行すると、特にループやホットパスでは時間を無駄にします。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("[0-9]+")
fmt.Println(re.MatchString("x9"))
}一度コンパイルし、何度も再利用する
原則は、パターンを一度コンパイルし、*regexp.Regexp を再利用することです。パッケージレベルの変数にするのが一般的です。
package main
import (
"fmt"
"regexp"
)
var numRe = regexp.MustCompile("[0-9]+")
func hasNumber(s string) bool {
return numRe.MatchString(s)
}
func main() {
fmt.Println(hasNumber("a1"))
fmt.Println(hasNumber("abc"))
}ループ内でのコンパイルを避ける
ループ内で MustCompile を呼び出してはいけません。ループの前でコンパイルし、各反復で同じ値を使用してください。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("[a-z]+")
inputs := []string{"go", "123", "rust"}
for _, s := range inputs {
fmt.Println(s, re.MatchString(s))
}
}Regexp は安全に共有できる
コンパイル済みの *regexp.Regexp は、複数のゴルーチンから並行して安全に使用できます。グローバルなインスタンスを1つ用意して、すべてのゴルーチンで利用できます。
package main
import (
"fmt"
"regexp"
)
var re = regexp.MustCompile("go")
func main() {
fmt.Println(re.MatchString("golang"))
}strings のほうが速い場合もある
固定されたリテラル部分文字列には、正規表現よりも strings.Contains のほうが適しています。本格的なパターン機能が必要な場合だけ、正規表現を使ってください。
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Contains("hello world", "world"))
}アンカー付きパターンを優先する
^ でアンカーを付けると、文字列全体をスキャンする代わりに、先頭が一致しない時点でエンジンがすぐに失敗できます。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("^https?://")
fmt.Println(re.MatchString("http://site"))
fmt.Println(re.MatchString("see http://x"))
}マッチ数を制限する
必要なマッチが少数だけの場合は、-1 の代わりに小さな n を Find-all メソッドに渡して、早めに処理を止めてください。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("[0-9]+")
fmt.Println(re.FindAllString("1 2 3 4 5", 2))
}バックトラッキングパターンに注意する
Go の RE2 エンジンは壊滅的なバックトラッキングを避けますが、.* のように範囲が広すぎるパターンでは、必要以上にスキャンすることがあります。具体的なパターンを指定してください。
package main
import (
"fmt"
"regexp"
)
func main() {
broad := regexp.MustCompile(".*=.*")
precise := regexp.MustCompile("[a-z]+=[0-9]+")
fmt.Println(broad.MatchString("x=1"), precise.MatchString("x=1"))
}動的な入力をエスケープする
パターンにユーザー入力を含める場合は、regexp.QuoteMeta でエスケープし、特殊文字がリテラルとして扱われるようにしてください。
package main
import (
"fmt"
"regexp"
)
func main() {
user := "a.b"
re := regexp.MustCompile(regexp.QuoteMeta(user))
fmt.Println(re.MatchString("a.b"))
fmt.Println(re.MatchString("axb"))
}コンパイル済みパターンをキャッシュする
パターンを実行時に組み立てる場合は、パターン文字列をキーにしてコンパイル済みのパターンをマップに保存し、同じパターンの再コンパイルを避けてください。
package main
import (
"fmt"
"regexp"
)
var cache = map[string]*regexp.Regexp{}
func get(p string) *regexp.Regexp {
if re, ok := cache[p]; ok {
return re
}
re := regexp.MustCompile(p)
cache[p] = re
return re
}
func main() {
fmt.Println(get("[0-9]+").MatchString("7"))
}すべてを組み合わせる
適切に調整されたバリデーターは、一度だけコンパイルし、パターンにアンカーを付け、すべての呼び出しで共有します。
package main
import (
"fmt"
"regexp"
)
var emailRe = regexp.MustCompile("^[a-z0-9]+@[a-z]+\\.[a-z]+$")
func main() {
fmt.Println(emailRe.MatchString("me@site.com"))
}確認問題
正規表現のパフォーマンスに関する最も重要なポイントは何でしょうか。
まとめ:パフォーマンスのヒント
正規表現を効率的に使う方法を学びました。
MustCompileで一度だけコンパイルして再利用します。並行利用にも安全です。- 固定された部分文字列には
stringsを優先し、パターンにアンカーを付け、マッチ数を制限します。 - 動的な入力は
QuoteMetaでエスケープし、実行時に作成するパターンをキャッシュします。
package main
import (
"fmt"
"regexp"
)
var re = regexp.MustCompile("^\\d{4}$")
func main() {
for _, s := range []string{"1234", "12"} {
fmt.Println(s, re.MatchString(s))
}
}よくある質問
「パフォーマンスのヒント」レッスンは無料ですか?
はい。「パフォーマンスのヒント」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「パフォーマンスのヒント」で何を学びますか?
コンパイル済みregexpを再利用します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「パフォーマンスのヒント」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。