regexp.Compile必须检查error,否则re为nil导致后续调用panic;动态拼接用户输入需QuoteMeta转义;\d仅匹配ASCII数字,Unicode数字须用\p{Nd}。

regexp.Compile 必须检查 error,否则 runtime panic
Go 的 regexp.Compile 永远返回两个值:*regexp.Regexp 和 error。它不会 panic,也不会自动忽略错误 —— 但如果你只写 re := regexp.Compile(...),就等于丢弃了 error,后续调用 re.FindString 等方法时,re 是 nil,直接触发 panic: runtime error: invalid memory address or nil pointer dereference。
常见错误现象:
- 正则里漏写右括号,比如
`(\d{3}-\d{2}` - 用了未定义的转义,比如
`\Q`(Go 不支持)或`\u`后面没跟合法码点 - 量词嵌套错误,如
`a++`
正确做法始终是:
re, err := regexp.Compile(`\d{3}-\d{2}-\d{4}`)
if err != nil {
log.Fatal(err) // 或 return err,或按业务逻辑处理
}
matches := re.FindString([]byte("123-45-6789"))
线上服务中若正则固定且可信(如校验邮箱格式),可用 regexp.MustCompile 省略 error 判断;但任何来自配置、API、表单的 pattern,必须用 Compile + 显式判断。
动态正则拼接用户输入前必须 quotemeta
用户输入的内容(比如搜索关键词 "foo.bar")如果直接塞进正则,. 会被当作元字符匹配任意字符,导致意外匹配或性能爆炸。Go 没有内置的 preg_quote,得手动用 regexp.QuoteMeta 转义。
例如要高亮用户输入的关键词:
keyword := "foo.bar"
escaped := regexp.QuoteMeta(keyword) // → "foo\.bar"
re := regexp.MustCompile(escaped)
highlighted := re.ReplaceAllString("this is foo.bar and foobar", "[[$0]]")
不加 QuoteMeta 的后果:
-
"a.c"会匹配"abc"、"axc"、"a c",而非字面量"a.c" - 含
*、+、?、[等字符时,正则语法直接报错
注意:QuoteMeta 会把所有非字母数字字符都加上 \,所以它只适合“字面量匹配”,不适合需要保留部分元字符语义的场景(比如允许用户用 * 表示通配,那就得自己解析并重写正则)。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
FindString* vs FindSubmatch*:选对系列避免类型转换和内存开销
Go 正则 API 分两套:以 String 结尾的(如 FindString、FindAllStringSubmatch)操作 string,返回 string 或 [][]string;以 Submatch 结尾的(如 FindSubmatch、FindAllSubmatch)操作 []byte,返回 []byte 或 [][]byte。
绝大多数情况该用 String 系列:
- 输入是
string,输出也要string,语义清晰,不用反复string(b)或[]byte(s) -
FindAllStringSubmatch只在有捕获组时才返回子匹配,而FindAllString直接返回全部匹配项,更直观 - 除非你在高频解析日志、做流式处理且已复用
[]byte缓冲区,否则没必要为省几个字节拷贝去用Submatch系列
一个典型误用:
// ❌ 错:输入 string,却用 Submatch 方法,还得转 b := []byte(text) matches := re.FindAllSubmatch(b, -1) // 返回 [][]byte // ✅ 对:直接用 String 系列 matches := re.FindAllString(text, -1) // 返回 []string
Go 正则不支持后向断言,Unicode 数字需显式写 \p{Nd}
Go 的 regexp 包基于 RE2 引擎,不支持 Perl/Python 那些高级特性,比如 (? 后向断言、(?!...) 负向先行断言。想实现“匹配后面是空格的数字”,不能写 \d+(?=\s),得换思路:用捕获组 + FindStringSubmatchIndex 手动切片,或改用 FindAllStringIndex 再验证上下文。
另一个常踩的坑是数字匹配:
-
\d在 Go 中只匹配 ASCII 数字0–9,不匹配中文数字(一、二)、阿拉伯数字(٠١٢)或带圈数字(①) - 要匹配 Unicode 数字,必须用
\p{Nd}(Number, decimal digit) - 中文字符用
\p{Han},emoji 用\p{Emoji},但注意这些属性类默认不启用,得确保正则字符串本身不含语法错误(\p{Han}是合法的,\p{HAN}就非法)
简单验证是否支持某属性类的方法:编译时看 err 是否非 nil。没有文档说“哪些 \p{} 支持”,只有实测或查 RE2 官方支持列表。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










