regexp.compile 返回 nil 时 panic 的根本原因是未检查 error 就直接使用 nil 的正则对象;必须先判断 err != nil,动态正则禁用 mustcompile,中文匹配应避免 \u4e00-\u9fa5 等不完整范围,而用更广的 unicode 区间或 unicode.is 配合 rune 判断。

regexp.Compile 返回 nil 时 panic,不是正则“写得不对”,而是你没检查 error
regexp.Compile 报 panic:先看 error 再用指针
常见错误现象:panic: runtime error: invalid memory address or nil pointer dereference
发生在调用 re.FindString 或任何方法时,但 re 是 nil
原因很直接:re, err := regexp.Compile(<code>\d{3}-\d{2}-\d{4}) 这行本身不会 panic;但如果你跳过 if err != nil 判断,直接用 re,而正则有语法错(比如括号不配对、量词重复),re 就是 nil,一调就崩。
必须这样做:
- 永远先判断
err,不能解包忽略 - 动态正则(来自用户输入、配置文件)禁用
regexp.MustCompile—— 它 panic 不可 recover - 静态字面量正则才用
MustCompile,且只用于启动期已知合法的模式
示例正确写法:
re, err := regexp.Compile(`https?://([^/]+)`)
if err != nil {
log.Printf("invalid regex: %v", err)
return
}
matches := re.FindStringSubmatch([]byte("https://www.php.cn/link/8b32107d42e4b4f4b0ebb1e4ed1d7c28"))
中文匹配不到:别信 [\u4e00-\u9fa5]
这个范围漏掉大量合法中文字符:扩展 A/B 区汉字(如“?”)、全角标点(“。”、“〇”)、日韩兼容汉字(“々”、“〆”),甚至部分拼音字母带重音(“é”)。
Go 的 RE2 引擎不支持 \p{Han},所以:
-
[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u3000-\u303f\uff00-\uffef]是更宽泛但依然有限的替代方案 - 真要按 Unicode 标准识别“汉字”,得放弃正则,改用
unicode.Is(unicode.Scripts["Han"], r)逐 rune 判断 - 若文本量不大(几千字符以内),性能无感;百万级文本建议先用粗粒度正则过滤,再细判
别写:
regexp.MustCompile(`[\u4e00-\u9fa5]+`) // ❌ 漏字多,维护难
可以写:
re := regexp.MustCompile(`[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u3000-\u303f\uff00-\uffef]+`)
FindAllStringSubmatch 返回空 slice:你没加捕获组
这个函数只返回有括号的子匹配(即 (...) 内容),不是“所有匹配的子串”。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
例如:
re := regexp.MustCompile(`https?://([^/]+)`)
matches := re.FindAllStringSubmatch([]byte("https://www.php.cn/link/8b32107d42e4b4f4b0ebb1e4ed1d7c28/pkg"))
matches 是空 slice?不是没匹配上,是 FindAllStringSubmatch 只返回 submatches[1](即 ([^/]+) 那部分),而 matches 本身是完整匹配结果的切片 —— 你真正该用的是 re.FindSubmatch 或 re.FindStringSubmatch(单次)。
想提取协议和域名,推荐:
- 用
FindStringSubmatch得到完整匹配(如"@#@#@#@#@#@#@#@#@#@0") - 再用带捕获组的正则 +
FindSubmatch提取子内容
. 不匹配换行符:多行文本要加 (?s)
默认 . 不匹配 \n,所以 <code>first.*third 在含换行的字符串里永远不匹配。
解决方式只有两个靠谱的:
- 用
<code>(?s)first.*third—— 单行模式,.匹配一切(含换行) - 用
<code>first[\s\S]*third—— 字符类绕过限制,语义明确
别用 [\w\W] 或 [\d\D],Go 的 \w 和 \d 默认不覆盖 Unicode,[\s\S] 最稳。
还有个坑:Windows 换行是 \r\n,\s 能覆盖它,所以 [\s\S] 也兼容。
正则在 Go 里不是“写出来就能跑”,核心约束来自三处:RE2 引擎限制、Go 字符串转义规则、UTF-8 字节序列前提。最容易被忽略的是——你以为传进去的是字符串,其实它可能是非法 UTF-8;你以为正则写对了,其实编译器先帮你吃掉了反斜杠。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










