regexgojavascriptre2

Regular Expressions Explained — JavaScript vs Go RE2 Differences

·8 min read

What is a Regular Expression?

A regular expression (regex) is a sequence of characters that defines a search pattern. Regex engines scan a string looking for substrings that match the pattern. They are used for validation, parsing, search-and-replace, and text extraction.

Basic Regex Syntax

.       any character except newline
\d      digit (0-9)
\w      word character (A-Za-z0-9_)
\s      whitespace
^       start of string
$       end of string
[abc]   character class — a, b, or c
[^abc]  negated class — anything except a, b, c
a|b     alternation — a or b
a*      zero or more a
a+      one or more a
a?      zero or one a
a{3}    exactly 3 a's
a{3,5}  3 to 5 a's
(abc)   capture group
(?:abc) non-capturing group

Capture Groups and Named Groups

javascript
// Unnamed capture groups
const m = "2024-05-18".match(/(d{4})-(d{2})-(d{2})/);
console.log(m[1], m[2], m[3]); // => "2024" "05" "18"

// Named capture groups (ES2018+)
const m2 = "2024-05-18".match(/(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/);
console.log(m2.groups.year);   // => "2024"

Go RE2 Engine

Go uses the RE2 regex engine — not PCRE (Perl-Compatible Regular Expressions) used by most other languages. RE2 guarantees linear time matching, which means regex cannot cause catastrophic backtracking. This is a security feature, not a limitation.

go
import "regexp"

re := regexp.MustCompile(`(d{4})-(d{2})-(d{2})`)
match := re.FindStringSubmatch("2024-05-18")
// match[0] = "2024-05-18" (full match)
// match[1] = "2024"
// match[2] = "05"
// match[3] = "18"

// Named groups
re2 := regexp.MustCompile(`(?P<year>d{4})-(?P<month>d{2})-(?P<day>d{2})`)
names := re2.SubexpNames()

JavaScript vs Go RE2 Differences

FeatureJavaScriptGo RE2
Lookahead (?=...)SupportedNot supported
Lookbehind (?<=...)Supported (ES2018+)Not supported
Backreferences \1SupportedNot supported
Named groups (?P<name>)(?<name>) syntax(?P<name>) syntax
Atomic groups (?>...)SupportedNot supported
Time complexityExponential worst caseO(n) guaranteed

If your regex uses lookaheads or backreferences, it will work in JavaScript but fail in Go. Rewrite the pattern to avoid them, or do multiple passes.

Common Patterns

Email:     [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
URL:       https?://[\w\-._~:/?#\[\]@!$&'()*+,;=%]+
IP v4:     \b(?:\d{1,3}\.){3}\d{1,3}\b
Date YYYY-MM-DD: \d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])
UUID:      [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}

Avoiding Catastrophic Backtracking

Patterns like (a+)+ can take exponential time on certain inputs in PCRE engines (ReDoS — Regular Expression Denial of Service). This is why Go chose RE2. If you deploy user-supplied regex patterns in a JavaScript server, validate them or use a RE2-compatible library.

Use JSONKit's Regex Tester to test patterns against your input, see all matches with line and column numbers, and get RE2 compatibility warnings if your pattern uses unsupported features.

Try Regex Tester

Test regex patterns with match highlighting, capture groups, and Go RE2 compatibility notes.