
本文详解 go 中 `encoding/xml` 包的典型误用:将 xml 字节流错误地交由 `json.unmarshal` 解析,导致“invalid character '
在 Go 中,encoding/xml 和 encoding/json 是两套独立的序列化/反序列化机制,不可混用。问题中的核心错误在于:先用 xml.Marshal() 生成 XML 格式字节(如
✅ 正确做法是:Marshal 与 Unmarshal 必须使用同一编码包。修复只需一行:
// ❌ 错误:用 json.Unmarshal 解析 XML 数据 err = json.Unmarshal(data, &pXml) // ✅ 正确:用 xml.Unmarshal 解析 XML 数据 err = xml.Unmarshal(data, &pXml)
此外,为确保字段可被 XML 包正确处理,还需注意以下关键点:
- 导出性要求:XML 只能序列化/反序列化首字母大写的导出字段(如 X, Y, Names),小写字段(如 z)会被忽略(这与 JSON 行为一致);
-
切片字段支持:[]string 类型可直接映射为多个同名 XML 元素(如
Bob Alice ),无需额外标签; - 可选:添加 XML 标签优化输出(推荐):
type Point struct {
X int `xml:"x"` // 自定义元素名
Y int `xml:"y"`
Names []string `xml:"name"` // 更语义化的标签名
}完整可运行示例:
package main
import (
"encoding/xml"
"fmt"
)
type Point struct {
X, Y int
z int // 小写字段 → 被忽略
Names []string
}
func main() {
p := Point{X: 1, Y: 2, Names: []string{"Bob", "Alice"}}
// 序列化为 XML
data, err := xml.Marshal(p)
if err != nil {
panic(err)
}
fmt.Printf("XML: %s\n", string(data))
// ✅ 正确:用 xml.Unmarshal 反序列化
var pXml Point
err = xml.Unmarshal(data, &pXml)
if err != nil {
panic(err) // 此处不再报错
}
fmt.Printf("Unmarshalled XML: %+v\n", pXml)
}? 注意事项总结:
- 永远匹配 Marshal/Unmarshal 所属包:xml.Marshal ↔ xml.Unmarshal,json.Marshal ↔ json.Unmarshal;
- XML 默认以结构体名作为根元素(如
),可通过 xml:"name,attr" 等标签精细控制; - 若需兼容 HTTP 响应等带 XML 声明()或注释的文档,xml.Unmarshal 可自动跳过前置内容;
- 对于含命名空间、CDATA 或复杂嵌套的 XML,建议结合 xml.Name 字段和自定义 UnmarshalXML 方法处理。
遵循以上原则,即可安全、高效地在 Go 中完成 XML 的双向数据绑定。










