Go 语言正则表达式

regexp 的编译、匹配、分组、替换,以及 RE2 的性能特性。

Intermediate
Key PointsGo 用 RE2 引擎,保证线性时间——没有回溯,所以不支持反向引用和环视。

编译与匹配

Go
// 编译一次,重复使用(推荐)
re := regexp.MustCompile(`\d{3}-\d{4}`)

fmt.Println(re.MatchString("电话 555-1234"))
fmt.Println(re.FindString("电话 555-1234"))

// 一次性使用
ok, _ := regexp.MatchString(`^a`, "abc")
fmt.Println(ok)
Output
true
555-1234
true

MustCompile panics on a bad pattern — fine for package-level vars (a broken regex is a programmer error, fail fast). For runtime-built patterns use regexp.Compile and handle the error.

查找

Go
re := regexp.MustCompile(`(\w+)@(\w+)\.com`)

s := "联系 tom@example.com 或 jerry@test.com"

fmt.Println(re.FindString(s))            // 第一个整体匹配
fmt.Println(re.FindAllString(s, -1))     // 全部,-1 表示不限

// 分组:FindStringSubmatch
m := re.FindStringSubmatch(s)
fmt.Println(m)                           // [整体 组1 组2]

// 全部匹配的分组
for _, g := range re.FindAllStringSubmatch(s, -1) {
	fmt.Println(g[1], g[2])
}
Output
tom@example.com
[tom@example.com jerry@test.com]
[tom@example.com tom example]
tom example
jerry test
MethodReturns
MatchStringbool
FindString第一个匹配的字符串
FindStringIndex起止下标 [2]int
FindStringSubmatch含分组的 []string
FindAllString全部匹配
ReplaceAllString替换后的字符串

替换

Go
re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)

// $1 $2 引用分组
fmt.Println(re.ReplaceAllString("2026-10-31", "$3/$2/$1"))

// 用函数替换
out := re.ReplaceAllStringFunc("2026-10-31 与 2025-01-01", func(s string) string {
	return "[" + s + "]"
})
fmt.Println(out)

// 转义用户输入
fmt.Println(regexp.QuoteMeta("1+1=2"))
Output
31/10/2026
[2026-10-31] 与 [2025-01-01]
1\+1=2

When interpolating user input into a pattern, always regexp.QuoteMeta — otherwise characters like (, * and + break or invalidate the pattern.

RE2 的限制

FeatureSupportedWorkaround
反向引用 \1不支持用代码二次校验
环视 (?=) (?<=)不支持改写正则或用两次匹配
原子组 (?>...)不支持不需要,RE2 无回溯
命名分组 (?P<x>)支持—
非贪婪 *?支持—

RE2's big win is no ReDoS: matching is O(n·m) for any input. The cost is no backreferences or lookaround — many PCRE patterns must be rewritten.

命名分组

Go
re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})`)

m := re.FindStringSubmatch("2026-10")
for _, name := range re.SubexpNames() {
	if name != "" {
		fmt.Println(name, "=", m[re.SubexpIndex(name)])
	}
}
Output
year = 2026
month = 10
Regexes get unreadable fast — comment them or use (?x) verbose mode. For HTML, JSON or CSV, use a real parser, never a regex.

Friends & Partners