This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →Go regex tester — RE2 rules, including why lookaround and backreferences don't compile
Ships in: Go, ripgrep (default mode), Rust regex (closely related engine)
Want to test your own pattern under Go RE2 (regexp, Go 1.22+)? Open the regex tester with this flavor already selected.
Open the regex tester — Go RE2 (regexp, Go 1.22+) →Go's standard-library regexp package, and by extension ripgrep's default matching mode, both run on RE2 — an engine built around one deliberate, load-bearing constraint: every pattern it accepts must be guaranteed to match in linear time relative to the input, no exceptions. That guarantee is the whole reason this flavor's row in the flavor table looks so much shorter than the others, and it's worth understanding why before you paste in a pattern written for anything else.
RE2 has no backreferences and no lookaround of any kind — not lookahead, not lookbehind, not negative or positive. This is not a performance limitation the way it might be elsewhere; it is architectural. Backreferences and lookaround both require, in the general case, exponential-time backtracking to resolve, which is exactly the guarantee RE2 exists to rule out. A pattern using \1, (?=...), (?!...), (?<=...) or (?<!...) does not run slowly here — it fails to compile at all, with an error naming the construct, the same honest refusal this tool gives you rather than a silent fallback to some other engine.
This is the single most common reason a PCRE2 or Perl pattern "ported to Go" breaks: the developer discovers the missing construct in a build failure, sometimes in CI, sometimes in production, because nothing in a typical development loop tests pattern compilation against RE2 specifically until Go actually tries to compile it. Running the pattern through this page under the Go RE2 flavor first catches exactly that failure before it reaches a build.
Named-group syntax is a second, smaller trap. (?P<name>...) has worked in Go's regexp package since it was introduced; the angle-bracket-only spelling, (?<name>...), is only accepted from Go 1.22 onward. If your code needs to support older Go toolchains, (?P<name>...) is the more portable choice even though both compile identically on a current release — and it's also the spelling RE2 shares with Python, which makes named-group patterns easier to keep in sync across a Go backend and a Python data pipeline.
Replacement templates have their own well-known trap: $1x in a Go ReplaceAll template does not mean "group 1, followed by a literal x" — Go's replacement parser reads it greedily as "the group named 1x", which almost never exists, so the replacement silently produces nothing where you expected the captured text plus a suffix. ${1}x is the fix, and it's one of the specific per-target notes this tool's Code tab attaches to every Go snippet it generates, precisely because it's easy to miss until a replacement quietly comes out wrong.
None of this makes RE2 a lesser engine — for the workloads Go and ripgrep are actually built for (searching large inputs, often user-supplied or adversarial, where a hostile pattern must never be allowed to hang the process) RE2's linear-time guarantee is the correct trade, and it's the same property this tool's own Analyse tab exists to help you achieve by hand in flavors that don't enforce it for you.
The upside of all these restrictions is that RE2 leaves very little room for surprise once a pattern compiles: no lookaround means no ambiguity about what a match consumes versus merely asserts, and no backreferences means the engine's own worst case is bounded by the pattern's size rather than the input's, which is exactly why Go's regexp package needs no step budget, no Analyse tab and no ReDoS witness of the kind this tool builds for every other flavor here — the class of bug those exist to catch cannot occur under RE2 by construction.
\d, \w and \s are ASCII-only by default in RE2, same as JavaScript and unlike Python or .NET — reach for the \p{...} Unicode property classes explicitly (\p{L} for any letter, \p{Nd} for a decimal digit in any script) if a pattern needs to match beyond the ASCII range, the same explicit opt-in JavaScript requires under its u or v flag.
Go RE2 (regexp, Go 1.22+) quirks, at a glance
The same facts this tool's engine implements and tests against — not a separate, unverified summary.
- No backreferences and no lookaround of any kind — not slower, absent. A pattern using either fails to compile, full stop.
- This is deliberate: RE2 guarantees linear-time matching, which backreferences and lookaround both make impossible to guarantee in general.
- Named-group replacement is parsed greedily: $1x in a replacement template means "the group named 1x", not "group 1 followed by x" — write ${1}x instead.
- (?<name>...) is only accepted from Go 1.22 onward; (?P<name>...) has always worked and is the more portable spelling.
A worked example: Go (regexp)
Extracting a date like 2026-08-22 — (?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}).
regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
Uses a raw backtick string, since the pattern contains no backtick itself and every backslash can stay single.
Frequently asked questions
- Why won't my lookahead pattern compile in Go?
- Go's regexp package (RE2) has no lookaround of any kind — no lookahead, no lookbehind, positive or negative — and no backreferences either. This is architectural, not a missing feature: RE2 guarantees linear-time matching, which both constructs would make impossible to guarantee in general.
- Should I use (?P<name>...) or (?<name>...) in Go?
- (?P<name>...) works on every Go version and also matches Python's spelling. (?<name>...) only compiles from Go 1.22 onward, so it's the less portable choice if you need to support older toolchains.
- Why did $1x disappear from my Go replacement?
- Go's ReplaceAll parses $1x greedily as "the group named 1x", which normally doesn't exist, rather than "group 1 followed by the literal x". Write ${1}x instead to get the intended result.
- Does ripgrep have the same limitations as Go's regexp?
- By default, yes — ripgrep's default matching mode is RE2-based, with the same lack of lookaround and backreferences. Its -P flag switches to a PCRE2 backend where those constructs are available, at the cost of RE2's linear-time guarantee.
Other flavors
ECMAScript RegExp, exactly as your browser or Node runs it
the engine behind PHP's preg_* and most Apache/nginx rewrite rules
re module rules, Unicode-by-default, 3.11+ possessive quantifiers
java.util.regex rules for Java, Kotlin, Scala and Android
System.Text.RegularExpressions rules, including the group-numbering quirk
POSIX ERE and leftmost-longest matching, not leftmost-first
POSIX BRE, where ( ) and { } are literal and \( \) \{ \} do the work