Regex in Go

Go's regexp package implements RE2 syntax — a guaranteed-linear-time regex engine. This means no backtracking, which makes Go regex safe from catastrophic backtracking (ReDoS) but also means some features like lookaheads and backreferences are not supported.

Code Examples

Basic matching

package main

import (
    "fmt"
    "regexp"
)

func main() {
    matched, _ := regexp.MatchString(`\d{3}-\d{4}`, "Call 555-1234")
    fmt.Println(matched) // true

    // Compile for reuse (preferred)
    re := regexp.MustCompile(`[a-z]+@[a-z]+\.[a-z]+`)
    fmt.Println(re.MatchString("user@example.com")) // true
}

regexp.MatchString() is a one-off check. For repeated use, compile with regexp.MustCompile() (panics on invalid pattern) or regexp.Compile() (returns an error).

Find and extract matches

package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(\d+)\.(\d+)`)
    text := "Versions: 1.21, 2.0, 3.14"

    // FindString: first match
    fmt.Println(re.FindString(text)) // "1.21"

    // FindAllString: all matches
    fmt.Println(re.FindAllString(text, -1))
    // ["1.21", "2.0", "3.14"]

    // FindStringSubmatch: match + groups
    m := re.FindStringSubmatch(text)
    fmt.Println(m) // ["1.21", "1", "21"]
}

Find methods come in variants: FindString (first match), FindAllString (all matches), FindStringSubmatch (match with groups). The -1 argument means find all.

Named capture groups

package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(
        `(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`,
    )
    match := re.FindStringSubmatch("2026-03-08")
    names := re.SubexpNames()

    result := make(map[string]string)
    for i, name := range names {
        if i > 0 && name != "" {
            result[name] = match[i]
        }
    }
    fmt.Println(result)
    // map[day:08 month:03 year:2026]
}

Go uses (?P<name>...) syntax for named groups (same as Python). SubexpNames() returns group names by index. There's no direct map accessor — you build it manually.

Replace with ReplaceAllString

package main

import (
    "fmt"
    "regexp"
    "strings"
)

func main() {
    re := regexp.MustCompile(`(\w+)\s(\w+)`)

    // Simple replacement with group references
    result := re.ReplaceAllString("John Smith", "$2, $1")
    fmt.Println(result) // "Smith, John"

    // Replace with a function
    upper := re.ReplaceAllStringFunc("hello world", strings.ToUpper)
    fmt.Println(upper) // "HELLO WORLD"
}

ReplaceAllString() supports $1, $2 group references. ReplaceAllStringFunc() accepts a function for dynamic replacements — but the function only receives the full match, not individual groups.

Split with regex

package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\s*[,;]\s*`)
    parts := re.Split("one, two; three,  four", -1)
    fmt.Println(parts) // ["one", "two", "three", "four"]
}

regexp.Split() works like strings.Split() but accepts a regex pattern. Pass -1 to get all substrings.

Note

Go uses the RE2 engine, which guarantees linear-time matching by disallowing backreferences and lookaround assertions. This makes Go regex immune to ReDoS attacks but means you cannot use lookaheads (?=), lookbehinds (?<=), or backreferences (\1) in patterns. Use raw string literals (backticks) to avoid backslash escaping issues.

Regex in Other Languages

Frequently Asked Questions

Why doesn't Go support lookaheads and lookbehinds?

Go uses the RE2 regex engine, which guarantees linear-time matching by design. Lookaheads and lookbehinds can cause exponential backtracking in worst-case scenarios, so RE2 excludes them. This is a deliberate trade-off: you lose some expressiveness but gain predictable performance and immunity to ReDoS attacks.

What is the difference between MustCompile() and Compile()?

regexp.Compile() returns (*Regexp, error) — use it when the pattern might be invalid (e.g., user input). regexp.MustCompile() panics if the pattern is invalid — use it for hard-coded patterns where a compile error would be a programmer bug.

How do I do case-insensitive matching in Go?

Add the (?i) flag at the start of your pattern: regexp.MustCompile(`(?i)hello`). Go supports inline flags: (?i) case-insensitive, (?m) multiline, (?s) dotall, (?U) ungreedy. There are no separate flag arguments like in Python or Java.

Can I use backreferences in Go regex?

No. Go's RE2 engine does not support backreferences (\1, \2, etc.) because they can cause exponential-time matching. If you need backreferences, you'll need to match the groups separately and compare them in Go code, or use a different regex library like github.com/dlclark/regexp2 which uses a .NET-compatible engine.

Want to test a Go regex pattern? Our regex tester runs JavaScript's native RegExp engine in your browser — paste your pattern and see matches in real time.

← Open the Regex Tester