应优先使用 regexp.MustCompile 处理硬编码正则,因其在启动时 panic 暴露语法错误;用户输入的正则必须用 regexp.Compile 并检查 error,避免 nil 指针 panic;FindAllString 第二参数控制匹配数量,分组捕获需用 FindStringSubmatch。

别用 regexp.MustCompile 处理用户输入,它会在非法正则上直接 panic,不是“更方便”,而是把错误藏得更深。
什么时候该用 regexp.MustCompile 而不是 regexp.Compile
绝大多数情况——只要正则表达式是写死在代码里的、启动时就确定的,比如校验邮箱格式、提取日志时间戳、匹配固定 API 响应字段,就该用 regexp.MustCompile。
- 它在程序初始化阶段就编译并检查语法,出错直接 panic,避免运行时才发现正则写错了
- 比
regexp.Compile少写三行 error 判断,包级变量定义清爽(例如var emailRe = regexp.MustCompile(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`)) - 性能无差异:两者底层都只编译一次,缓存结果;
MustCompile只是把 error 处理提前了
regexp.Compile 忘记检查 error 是最常见 panic 来源
一旦你从配置文件、HTTP query 或表单里读取正则 pattern,就必须用 regexp.Compile,且不能跳过 error 检查。
- 典型错误现象:
panic: runtime error: invalid memory address or nil pointer dereference,发生在调用re.FindString(...)时,因为re是 nil - 正确写法必须带 if 判断:
re, err := regexp.Compile(userPattern); if err != nil { return err } - 别试图用 recover 捕获
MustCompile的 panic——它不是设计来被 recover 的,而且掩盖了本该在启动时暴露的问题
FindString 和 FindAllString 的参数陷阱
这两个方法名字像,行为却关键不同,尤其 FindAllString 的第二个参数容易被忽略。
立即学习“go语言免费学习笔记(深入)”;
-
re.FindString(text):只返回第一个匹配的字符串,没匹配就返回空字符串""(不是nil) -
re.FindAllString(text, n):第二个参数n控制最多返回几个匹配项;n == -1表示全部,n == 0返回空切片,n > 0最多返回n个 - 注意:空匹配(比如
regexp.MustCompile(`a*`).FindAllString("b", -1))会返回[]string{"", "", ""}—— 这是 Go 正则引擎的标准行为,不是 bug
分组捕获时别用 FindString,要用 FindStringSubmatch
如果正则里写了括号 () 想提取子匹配,FindString 完全不返回分组内容,只会返回整个匹配串。
- 正确方式:
re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`); match := re.FindStringSubmatch([]byte("2024-05-21")),返回的是[]byte切片数组,match[0]是完整匹配,match[1]是第一组,依此类推 - 如果坚持用 string 类型接口,选
FindStringSubmatch,它返回[][]string,但注意:它对未匹配的组返回空字符串,不是nil - 别在循环里反复调用
MustCompile——它不便宜;把正则对象提成变量复用
真正容易被忽略的点是:正则是否“必须”动态编译,往往取决于数据来源而非功能需求。硬编码的 pattern 就不该留 runtime 错误空间,而用户可控的输入哪怕只用于调试,也得走 Compile + error 检查这条路。


















