
go 中 strings.split 无法按预期分割日期,往往是因为输入字符串中混入了视觉相似但 unicode 编码不同的“伪短横线”(如 u+2010、u+2013 等),导致 split 失败或切片长度异常。
go 中 strings.split 无法按预期分割日期,往往是因为输入字符串中混入了视觉相似但 unicode 编码不同的“伪短横线”(如 u+2010、u+2013 等),导致 split 失败或切片长度异常。
在 Go 中,strings.Split(s, sep) 是一个简单而强大的字符串分割工具,常被用于解析形如 "2015-10-04" 的 ISO 格式日期。但若实际输入并非标准 ASCII 连字符 '-'(Unicode U+002D),而是外观高度相似的其他 Unicode 破折号(如 – U+2013、— U+2014、‐ U+2010 等),strings.Split 将完全无法匹配,返回原字符串作为唯一元素的切片 —— 即 []string{"2015‐10‐04"},此时访问 month[1] 必然触发 panic: index out of range。
✅ 正确示例(使用标准 ASCII 连字符):
package main
import (
"fmt"
"strings"
)
func main() {
date := "2015-10-04" // ✅ U+002D × 2
parts := strings.Split(date, "-")
if len(parts) != 3 {
panic("invalid date format: expected 3 parts separated by '-'")
}
year, month, day := parts[0], parts[1], parts[2]
fmt.Printf("Year: %s, Month: %s, Day: %s\n", year, month, day)
// Output: Year: 2015, Month: 10, Day: 04
}
❌ 常见陷阱(隐形 Unicode 破折号):
date := "2015–10–04" // ❌ U+2013 EN DASH — looks identical but won't split!
parts := strings.Split(date, "-") // → []string{"2015–10–04"} (length = 1)
// parts[1] → panic!
? 快速诊断方法:
打印每个字符的 Unicode 码点,确认分隔符真实身份:
for i, r := range date {
fmt.Printf("char[%d]: %q (U+%04X)\n", i, r, r)
}
// 若输出中出现 U+2010、U+2013、U+FF0D 等,即为“假短横线”
? 解决方案:
-
预处理清洗:将常见破折号统一替换为标准 '-':
import "strings" func normalizeDash(s string) string { replacements := []struct{ old, new string }{ {"–", "-"}, // U+2013 en dash {"—", "-"}, // U+2014 em dash {"‐", "-"}, // U+2010 hyphen {"−", "-"}, // U+2212 minus sign {"-", "-"}, // U+FF0D fullwidth hyphen } for _, r := range replacements { s = strings.ReplaceAll(s, r.old, r.new) } return s } date = normalizeDash(date) parts := strings.Split(date, "-") -
健壮性防护:始终校验切片长度再索引:
parts := strings.Split(date, "-") if len(parts)
? 总结:strings.Split 行为“诡异”的根本原因几乎总是输入字符串中存在不可见的 Unicode 异构分隔符。开发中应养成对用户输入或富文本来源(如网页复制、Markdown 渲染、CMS 导出)的字符串做 Unicode 规范化或显式清洗的习惯,而非假设 - 就是 -。











