
本文详解如何在 Go 中正确使用 regexp 包匹配并提取字符串中所有 {...} 格式的占位符(如 {city}),涵盖无捕获全匹配与带捕获组的精准提取两种场景,并指出常见错误及最佳实践。
本文详解如何在 go 中正确使用 `regexp` 包匹配并提取字符串中所有 `{...}` 格式的占位符(如 `{city}`),涵盖无捕获全匹配与带捕获组的精准提取两种场景,并指出常见错误及最佳实践。
在 Go 中使用正则表达式提取花括号内的内容时,需特别注意语法细节和 API 选择。你遇到的空结果问题,主要源于三处典型错误:误加正则分隔符 /、未使用原始字符串字面量导致转义混乱、以及正则逻辑未适配目标结构。
✅ 正确写法一:提取完整匹配项(如 {city})
若只需获取所有形如 {xxx} 的完整子串,应使用 FindAllString,配合简洁、安全的正则模式:
package main
import (
"fmt"
"regexp"
)
func main() {
r := regexp.MustCompile(`{[^{}]*}`) // 原始字符串 + 无多余分隔符
matches := r.FindAllString("{city}, {state} {zip}", -1)
fmt.Println(matches) // 输出: [{city} {state} {zip}]
}- [^{}]* 表示“匹配零个或多个既不是 { 也不是 } 的字符”,比 [^}]* 更健壮(避免嵌套花括号干扰);
- 使用反引号包裹的原始字符串(` `)可避免双反斜杠转义,提升可读性与可靠性;
- 切勿添加 / 等分隔符——Go 的 regexp 不支持 Perl/JavaScript 风格的 /pattern/ 语法。
✅ 正确写法二:仅提取花括号内内容(如 city)
若目标是剥离 {}、只获取内部值(如 city, state, zip),需结合捕获组与 FindAllStringSubmatch:
r := regexp.MustCompile(`{([^{}]*)}`)
matches := r.FindAllStringSubmatch([]byte("{city}, {state} {zip}"), -1)
for _, m := range matches {
// m 是 [][]byte,m[0] 为完整匹配(如 "{city}"),m[1] 为第一个捕获组(即 "city")
fmt.Println(string(m[1])) // 输出: city\nstate\nzip
}⚠️ 注意:FindAllStringSubmatch 接收 []byte 类型输入,返回 [][]byte;若用 FindAllSubmatch(非 String 版本),需手动转换为字符串。
? 关键要点总结
- 不要写 /pattern/:Go 正则无分隔符,直接写 "{[^{}]*}" 即可;
- 优先用原始字符串:regexp.MustCompile({([^{}])}) 比 `"\{([^\}])\}"` 更清晰、更少出错;
- 避免贪婪陷阱:[^{}]* 显式排除花括号,比 .*? 更安全,防止跨区域误匹配;
-
区分 API 用途:
- FindAllString → 返回 []string,适合简单提取完整匹配;
- FindAllStringSubmatch → 返回 [][]byte,适合提取捕获组内容;
- 若需位置信息,可用 FindAllStringIndex。
掌握这些要点后,即可稳定、高效地从模板字符串中解析占位符,适用于配置渲染、文本替换等典型场景。


















