引入

处理字符串经常遇到”找一段符合某种规则的文本”——邮箱格式、日期提取、敏感词替换。strings 包只能做精确匹配,正则表达式才能描述复杂的文本模式。Go 的 regexp 包提供编译型正则,性能很好。

正文

定义

定义

正则表达式是一种用特殊语法描述文本模式的工具。Go 的 regexp 包提供编译型正则,先 Compile 编译模式,再对字符串做匹配、查找、替换等操作。

语法

import "regexp"
 
re := regexp.MustCompile(`\d+`)
fmt.Println(re.MatchString("abc123")) // true

例子

匹配

re := regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`)
fmt.Println(re.MatchString("2026-07-20")) // true
fmt.Println(re.MatchString("2026/07/20")) // false

MatchString 返回布尔值,^$ 分别锚定开头和结尾,确保整个字符串都符合模式。

查找

re := regexp.MustCompile(`\b\w+@\w+\.\w+\b`)
emails := re.FindAllString("联系 [email protected][email protected]", -1)
fmt.Println(emails) // [[email protected] [email protected]]

FindAllString 返回所有匹配结果,-1 表示不限制数量。

分组提取

re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
match := re.FindStringSubmatch("日期: 2026-07-20")
fmt.Println(match[0]) // 2026-07-20(完整匹配)
fmt.Println(match[1]) // 2026(年)
fmt.Println(match[2]) // 07(月)
fmt.Println(match[3]) // 20(日)

FindStringSubmatch 返回完整匹配加各分组捕获的内容。

命名分组

re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
match := re.FindStringSubmatch("2026-07-20")
names := re.SubexpNames()
result := map[string]string{}
for i, name := range names {
    if i > 0 && name != "" {
        result[name] = match[i]
    }
}
fmt.Println(result) // map[day:20 month:07 year:2026]

命名分组用 (?P<name>pattern) 语法,配合 SubexpNames() 提取成 map,可读性更好。

替换

re := regexp.MustCompile(`\d+`)
result := re.ReplaceAllString("第1名和第2名", "X")
fmt.Println(result) // 第X名和第X名

ReplaceAllString 把所有匹配替换成指定字符串。

函数替换

re := regexp.MustCompile(`\d+`)
result := re.ReplaceAllStringFunc("价格: 100 和 200", func(s string) string {
    n, _ := strconv.Atoi(s)
    return fmt.Sprintf("%d", n*2)
})
fmt.Println(result) // 价格: 200 和 400

ReplaceAllStringFunc 用函数动态生成替换内容,适合复杂替换逻辑。

编译复用

var emailRe = regexp.MustCompile(`[\w.]+@[\w.]+\.\w+`)
 
func isValidEmail(s string) bool {
    return emailRe.MatchString(s)
}

把编译好的正则存成包级变量,避免每次调用都重新编译。

常见写法

写法说明
regexp.MustCompile(pattern)编译正则(失败时 panic)
regexp.Compile(pattern)编译正则(返回 error)
re.MatchString(s)判断字符串是否匹配
re.FindString(s)返回第一个匹配
re.FindAllString(s, n)返回前 n 个匹配(-1 全部)
re.FindStringSubmatch(s)返回匹配 + 分组
re.ReplaceAllString(s, rep)替换所有匹配
re.ReplaceAllStringFunc(s, fn)函数替换
re.Split(s, n)按正则分割字符串
re.SubexpNames()获取分组名称

特点

  • Go 正则是编译型的,MustCompile 一次编译反复使用
  • MustCompile 编译失败直接 panic,适合包级初始化
  • Compile 返回 error,适合动态模式或需要错误处理的场景
  • 支持命名分组 (?P<name>pattern),提取更清晰
  • FindAllString(s, -1)-1 表示不限制数量
  • 把编译好的正则存为全局变量复用,避免重复编译
  • Go 正则语法基于 RE2,不支持回溯(lookaround),但性能稳定

理解

正则表达式就是给文本匹配写了一套规则描述语言。Go 的 regexp 包用编译模式,先编译后使用,性能很好。MustCompile 适合全局变量,FindStringSubmatch 配合命名分组能干净地提取结构化数据。记住把编译结果缓存起来,别在循环里反复编译。

引出

正则表达式处理字符串很强大,但在并发和网络编程中,怎么控制操作的生命周期和取消?接下来看 Go 上下文,学习 context.Context 怎么管理超时、取消和请求级数据传递。