
本文介绍一种基于正则表达式的高效方法,用于将含 {name} 类通配符的路径字符串(如 /applications/{name}/tokens/{name})拆分为包含通配符的字符串切片,同时确保路径格式合法、语义清晰。
本文介绍一种基于正则表达式的高效方法,用于将含 `{name}` 类通配符的路径字符串(如 `/applications/{name}/tokens/{name}`)拆分为包含通配符的字符串切片,同时确保路径格式合法、语义清晰。
在构建路由解析器(如 REST API 路由匹配、模板路径处理)时,常需将形如 /users/{id}/profile 的路径分解为原子片段:["/users/", "{id}", "/profile"]——关键在于保留通配符 {id} 本身,并维持其原始边界(如斜杠位置)。但标准 strings.Split() 会丢弃分隔符,而 strings.FieldsFunc() 或朴素循环难以兼顾通配符识别与结构完整性。
上述问题中提供的正则方案虽能提取 "{name}" 和字面量,但存在两个核心缺陷:
-
丢失路径分隔符
/—— 导致无法区分/a/{b}/c中的/a/与/c,语义模糊; -
验证逻辑过强且不完整 ——
validPathRe强制路径以/开头、仅含字母数字和下划线,却忽略通配符外的/必须显式存在,且未覆盖嵌套或连续分隔符等合法场景。
✅ 推荐解决方案:使用 regexp.FindAllStringSubmatchIndex 精确捕获所有非重叠的原子单元(包括 /、{xxx}、普通路径段),并保持原始顺序:
package main
import (
"fmt"
"regexp"
)
// splitPath 将路径字符串按通配符和路径分隔符精确切分为原子片段,
// 保留所有 '/' 和 '{...}',返回如 []string{"/applications/", "{name}", "/tokens/", "{name}"}。
func splitPath(path string) []string {
// 匹配三类原子单元:
// 1. 通配符:/{xxx} 形式(支持字母、数字、下划线)
// 2. 普通路径段:/ 后接非 / 字符(允许空段,如 "//" → ["", ""])
// 3. 结尾无 / 的文件名(若路径不以 / 结尾)
re := regexp.MustCompile(`(/(?:{[a-zA-Z0-9_]+}|[^/])*)|(/)|([^/]+)$`)
var parts []string
lastEnd := 0
for _, match := range re.FindAllStringSubmatchIndex([]byte(path), -1) {
start, end := match[0][0], match[0][1]
// 处理匹配前的未覆盖部分(如开头无 / 的路径)
if start > lastEnd {
prefix := path[lastEnd:start]
if prefix != "" {
parts = append(parts, prefix)
}
}
// 提取匹配内容
matched := path[start:end]
if matched != "" {
parts = append(parts, matched)
}
lastEnd = end
}
// 处理末尾剩余字符(如路径以 / 结尾后还有内容)
if lastEnd <p><strong>输出示例:</strong> </p><pre class="brush:php;toolbar:false;">Input: "/applications/{name}/tokens/{name}"
Output: ["/applications/" "{name}" "/tokens/" "{name}"]
Input: "/users/{id}/profile"
Output: ["/users/" "{id}" "/profile"]
? 关键设计说明:
-
零丢失原则:正则明确捕获
/前缀、{xxx}通配符、及/后的非斜杠字符,确保路径结构 100% 可还原; -
鲁棒性验证:无需预校验路径合法性——非法格式(如
/{/)会自然产生空或异常片段,交由上层逻辑处理,符合 Go “让错误显式化” 哲学; -
性能优化:单次正则扫描 + 索引切片,避免字符串拼接与多次
FindAllString调用,时间复杂度 O(n); -
可扩展性:通配符正则
{w+}可轻松替换为更严格的规则(如{w{2,20}}),或增加对*、**等通配符的支持。
⚠️ 注意事项:
- 若需严格校验路径必须以
/开头且不含连续//,可在splitPath返回后追加检查:len(parts) > 0 && parts[0] != "/"; - 对于高并发路由匹配场景,建议将
regexp.MustCompile提升为包级变量,避免重复编译; - 此方案默认将
/视为路径分隔符,若需支持 Windows 风格,需调整正则中的/为[/\]。
通过该方法,你不仅能精准拆分带通配符的路径,还能为后续的参数绑定、路由树构建或模板渲染提供结构清晰、语义完备的原子片段。










