strings.split 不是分词器,它按固定分隔符切分、不识别语义边界;gse 自定义词典需 utf-8 无 bom、严格格式“词 词频 词性”、且 loaddictionary 必须在 segment 前调用一次;取词须 string(s.text),停用词需手动过滤,词性标注需提前 addpos(true),并发不安全,输入须校验 utf-8 有效性。

为什么不用 strings.Split 做分词
strings.Split 是切分固定分隔符用的,不是分词器。它不识别语义边界,比如把 "人工智能" 拆成 "人工" 和 "智能" —— 这是错的;但 strings.Split("人工智能", "人") 会得到 ["", "工智能"],完全偏离中文分词目标。分词本质是基于词典或模型的序列标注/切分,不是字符串查找替换。
gse 加载自定义词典必须注意三件事
gse 默认内置简体词典,对新词、专有名词(如 "TiDB"、"小红书种草")基本无效。要提升准确率,必须加自定义词典,且容易踩坑:
- 文件编码必须是 UTF-8 无 BOM:Windows 记事本另存时选“UTF-8”,别选“UTF-8 with BOM”,否则
seg.LoadDictionary("dict.txt")静默失败,词典为空 - 每行格式严格为
词 词频 词性(空格分隔),例如:小红书 100 nz、TiDB 95 eng;词频越高越优先成词,想强制匹配长词(如小红书种草)就得设远高于子词的词频(如 500 vs 100) -
LoadDictionary必须在seg.Segment()之前调用,且只调用一次;重复加载不报错但无效,词典不会刷新
分词结果怎么安全取值和过滤
seg.Segment([]byte(text)) 返回 []gse.Segment,每个元素含 Text(类型是 []byte)、Start、End、Pos。常见错误是直接 fmt.Println(s.Text) —— 输出乱码,因为没转 string:
- 取词必须写
string(s.Text),不是string(rune(s.Text[0]))或其他转换 - 停用词过滤得自己做:
stops := map[string]bool{"的": true, "了": true},然后遍历判断!stops[word] - 要词性标注?必须提前调
seg.AddPos(true),否则s.Pos恒为空字符串 - 并发不安全:不能复用同一个
seg实例处理多个 goroutine;要么每次新建,要么用sync.Pool缓存
输入不是合法 UTF-8 会导致静默截断
Go 字符串默认 UTF-8,但 HTTP body、日志文件、数据库字段可能含非法字节(如 GBK 混入、截断的 emoji)。gse 遇到非法 UTF-8 字节会跳过整段,结果变短且无提示:
- 务必在分词前校验:
if !utf8.Valid([]byte(text)) { /* 处理或丢弃 */ } - 繁体字(如
"蘋果")不会自动转简体,需前置标准化:用github.com/mozillazg/go-unidecode转拼音,或golang.org/x/text/transform做繁简转换 - 不要依赖
strings.Fields或正则预清洗——它会破坏字节偏移,导致后续高亮、位置提取错位;清洗应放在分词后,或用 gse 自带的seg.RemovePunct()(需开启)
真正影响性能的从来不是分词算法本身,而是词典加载时机、UTF-8 校验缺失、以及并发复用 seg 实例——这三点出错,吞吐量直接掉一半,且问题难以复现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











