0Pricing
Go Academy · レッスン

パフォーマンスのヒント

コンパイル済み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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. regexpの基礎
  2. 検索と抽出
  3. テキストの置換
  4. パフォーマンスのヒント
← Go Academyに戻る