xml.Unmarshal 会 OOM,应改用 xml.Decoder 流式解析:它不构建完整树,支持逐 token 处理、局部解码、Skip 跳过无关节点,并需正确处理命名空间、属性(,attr)、文本(,chardata)、子元素及 innerxml。

xml.Unmarshal 会 OOM,别用它读大文件
Go 标准库的 xml.Unmarshal 必须把整个 XML 加载进内存再解析,百 MB 级文件很容易触发 runtime: out of memory。这不是配置问题,是设计使然——它面向结构已知、规模可控的场景。
- 哪怕只取其中 3 个字段,
xml.Unmarshal仍会构建整棵树 - 嵌套越深、文本越长(比如含大量 CDATA 或缩进空格),内存峰值越高
- 无法提前终止:一旦开始解析,必须跑完或 panic
用 xml.Decoder 逐 token 流式处理
真正能扛住 GB 级 XML 的只有 xml.NewDecoder + 手动 token 遍历。核心是不建完整树,只在需要时局部解构。
- 调用
decoder.Token()拿到xml.StartElement、xml.CharData或xml.EndElement - 用
strings.EqualFold(se.Name.Local, "item")匹配标签名,忽略命名空间前缀(如{http://ns}item) - 遇到目标节点后,用
decoder.DecodeElement(&item, &se)局部反序列化,避免手写字段赋值 - 不需要的深层嵌套直接调
decoder.Skip(),它内部递归跳过,比手动循环安全
解析混合内容(属性 + 文本 + 子元素)要拆开声明
像 <price currency="USD">29.99<unit>USD</unit></price> 这类节点,字段声明漏一环,数据就全丢。
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
- 属性必须显式加
,attr:例如Currency string `xml:"currency,attr"` - 纯文本内容用
,chardata:例如Value string `xml:",chardata"`(注意前面是逗号,不是点) - 子元素不能和文本共存于同一字段;需另设结构体字段,如
Unit *Unit `xml:"unit"` - 如果想原样保留子元素的 XML 字符串(比如 HTML 片段),用
,innerxml而不是,chardata
命名空间不是可选项,是解析开关
带 xmlns 的 XML(如 <rss xmlns="http://purl.org/rss/1.0/">)默认会被 xml.Unmarshal 和 xml.Decoder 完全跳过——不报错,也不填字段,静默失效。
立即学习“go语言免费学习笔记(深入)”;
- 用
decoder.Token()拿到xml.StartElement后,检查se.Name.Space是否非空 - 匹配时必须带上命名空间前缀:
se.Name.Local == "item" && se.Name.Space == "http://example.com/ns" - 若 XML 多命名空间混杂,别硬编码 URI,用
strings.HasSuffix(se.Name.Space, "rss/1.0")更健壮 XMLName xml.Name `xml:"http://purl.org/rss/1.0 rss"` 是唯一让 <code>xml.Unmarshal能识别根节点的方式,但仅限小文件
decoder.Skip() 不判空就调,下一次 Token() 必 panic。

















