Go 语言 XML 的序列与反序列化实践


导读

本文使用 Go 原生支持的包,对 XML 字符串以及 .xml 文件进行序列化与反序列化实践。同时对 Go 语言下的 JSON 序列化反序列化与 XML 的序列化反序列化进行性能测试与比对。

  • 使用到的包是 encoding/xml。详细文档可查看官方中文文档,链接为: https://studygolang.com/pkgdoc

  • Go 语言 JSON 的序列与反序列化博客已经更新:
    【Golang】Go 语言 JSON 的序列化与反序列化实践

  • 请留意代码块中的注释,注释中有表示出一些非常重要的细节!

  • 本文对 XML 的序列化与反序列化使用较基础,尚未对 XML 文件的标签属性等进行解析。若读者有需要,本文起到抛砖引玉的作用,详细的使用参见官方文档。


文章目录

  • Go 语言 XML 的序列与反序列化实践
    • 导读
    • 一. 案例提出
    • 一. XML 的序列化
      • 1. 序列化的简单示例
      • 2. 序列化的完整代码
    • 二. XML 的反序列化
      • 1. 反序列化的简单示例
      • 2. 反序列化的完整代码
    • 三. Go 语言下 JSON 与 XML 序列化反序列化性能测试
    • 四. 使用 io 流进行反序列化与序列化
    • 其他相关文章

一. 案例提出

我们以图书馆为原型进行建模。对于一个图书馆用 library.xml 文件进行描述。

<?xml version="1.0"?>
<Library><name>China library</name><location>China</location><isPrivate>false</isPrivate><score>4.6</score><date><open>2020-07-31T14:27:10.035542+08:00</open><close>2020-07-31T14:27:10.035542+08:00</close></date><bookInfo><number>1005</number><book><name>Go 语言 JSON 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T17:44:53.199855+08:00</publishTime></book><book><name>Go 语言 XML 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T17:44:53.199855+08:00</publishTime></book></bookInfo>
</Library>

下表对字段进行解释

字段名 类型 映射 Go 类型 解释
library - Library(自定义结构体) 图书馆根标签
name 字符串 string 图书馆名
location 字符串 string 所在地
isPrivate 布尔 bool 是否是私有图书馆
score 浮点数 float64 点评星级
date - Date(自定义结构体) 图书馆开馆闭馆
open 字符串 time.Time 开馆时间
close 字符串 time.Time 必馆时间
bookInfo - BookInfo(自定义结构体) 图书信息
number 整型 int 图书总数
book - Book(自定义结构体) 图书
(book) name 字符串 string 书名
(book) author 字符串 string 作者
(book) publishTime 字符串 time.Time 发布时间

Go 语言的结构体设计如下:
(其中 library.xml 文件中的标签字段名与 Go 结构体字段中的 xml 标签值一一对应)

package maintype Library struct {Name      string    `xml:"name"`Location  string    `xml:"location"`IsPrivate bool      `xml:"isPrivate"`Score     float64  `xml:"score"`Date      Date         `xml:"date"`BookInfo  BookInfo  `xml:"bookInfo"`}type Date struct {Open time.Time   `xml:"open"`Close   time.Time   `xml:"close"`
}type BookInfo struct {Number       int     `xml:"number"`BookList  []Book  `xml:"book"`
}type Book struct {Name         string      `xml:"name"`Author      string      `xml:"author"`PublishTime   time.Time   `xml:"publishTime"`
}

基于上述案例与模型进行序列化与反序列化。


一. XML 的序列化

1. 序列化的简单示例

在进行序列化对象为 .xml 文件之前,我们先创建一个 library 对象。

package mainimport "time"var library = Library{Name:      "一个图书馆",Location:  "中国",IsPrivate: true,Score:     4.9,Date: Date{Open:  time.Now(),Close: time.Now(),},BookInfo: BookInfo{Number: 1005,BookList: []Book{{Name: "Go 语言 JSON 序列化与反序列化",Author: "fxtack",PublishTime: time.Now(),},{Name:        "Go 语言 XML 序列化与反序列化",Author:      "fxtack",PublishTime: time.Now(),},},},
}

通过序列化我们可以将该对象变为一个 XML 字符串,并简单的打印输出:

package mainimport ("encoding/xml""fmt""log"
)func main(){// 序列化同在 main 包下的 libraryresult, err := xml.Marshal(&library)if err != nil {log.Println("对象序列化为 XML 字符串失败")}// result 是字节切片类型,要转为字符串再输出fmt.Println(string(result))
}

输出结果如下。

<Library><name>广东大图书馆</name><location>广东</location><isPrivate>false</isPrivate><score>4.6</score><date><open>2021-07-08T18:26:33.7720883+08:00</open><close>2021-07-08T18:26:33.7720883+08:00</close></date><bookInfo><number>1005</number><book><name>Go 语言 JSON 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T18:26:33.7720883+08:00</publishTime></book><book><name>Go 语言 XML 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T18:26:33.7720883+08:00</publishTime></book></bookInfo></Library>

很明显这个输出结果的格式太难看了,很长一条。Go 也有考虑到这个问题,因此我们可以使用 xml.MarshalIndent 方法来解决格式化输出的问题。

package mainimport ("encoding/xml""fmt""log"
)func main(){// 使用了 xml.MarshalIndent 来进行格式序列化// 第二个参数为 xml 每行的前缀// 第三个参数为标签嵌套时使用的空位符,这里选择用缩进值,也可以使用四个空格result, err := xml.MarshalIndent(&library, "", "\t")if err != nil {log.Println("对象序列化为 XML 字符串失败")}fmt.Println(string(result))
}

此时的输出就非常规范易读了。

<Library><name>广东大图书馆</name><location>广东</location><isPrivate>false</isPrivate><score>4.6</score><date><open>2021-07-08T18:34:52.9834418+08:00</open><close>2021-07-08T18:34:52.9834418+08:00</close></date><bookInfo><number>1005</number><book><name>Go 语言 JSON 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T18:34:52.9834418+08:00</publishTime></book><book><name>Go 语言 XML 序列化与反序列化</name><author>fxtack</author><publishTime>2021-07-08T18:34:52.9834418+08:00</publishTime></book></bookInfo>
</Library>

注意


无论是 xml.Marshal 还是 xml.MarshalIndent 方法,其传入的第一个参数值类型是 interface{} 类型,也就是用于进行序列化的对象。传入的可以是对象,也可以是对象的地址,以下代码的效果是相同的(以 xml.Marshal 为例),但是建议传入地址。

...
result, err := xml.Marshal(library)
...
...
result, err := xml.Marshal(&library)
...

2. 序列化的完整代码

完整的序列化过程需要对象序列化后输出为 .xml 文件。其流程如下:

#mermaid-svg-iI4jX4lVJlJ4IL8h .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .label text{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .node rect,#mermaid-svg-iI4jX4lVJlJ4IL8h .node circle,#mermaid-svg-iI4jX4lVJlJ4IL8h .node ellipse,#mermaid-svg-iI4jX4lVJlJ4IL8h .node polygon,#mermaid-svg-iI4jX4lVJlJ4IL8h .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-iI4jX4lVJlJ4IL8h .node .label{text-align:center;fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .node.clickable{cursor:pointer}#mermaid-svg-iI4jX4lVJlJ4IL8h .arrowheadPath{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-iI4jX4lVJlJ4IL8h .flowchart-link{stroke:#333;fill:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-iI4jX4lVJlJ4IL8h .edgeLabel rect{opacity:0.9}#mermaid-svg-iI4jX4lVJlJ4IL8h .edgeLabel span{color:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-iI4jX4lVJlJ4IL8h .cluster text{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-iI4jX4lVJlJ4IL8h .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-iI4jX4lVJlJ4IL8h text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .actor-line{stroke:grey}#mermaid-svg-iI4jX4lVJlJ4IL8h .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .sequenceNumber{fill:#fff}#mermaid-svg-iI4jX4lVJlJ4IL8h #sequencenumber{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h #crosshead path{fill:#333;stroke:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .messageText{fill:#333;stroke:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-iI4jX4lVJlJ4IL8h .labelText,#mermaid-svg-iI4jX4lVJlJ4IL8h .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .loopText,#mermaid-svg-iI4jX4lVJlJ4IL8h .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-iI4jX4lVJlJ4IL8h .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-iI4jX4lVJlJ4IL8h .noteText,#mermaid-svg-iI4jX4lVJlJ4IL8h .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-iI4jX4lVJlJ4IL8h .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-iI4jX4lVJlJ4IL8h .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-iI4jX4lVJlJ4IL8h .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .section{stroke:none;opacity:0.2}#mermaid-svg-iI4jX4lVJlJ4IL8h .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-iI4jX4lVJlJ4IL8h .section2{fill:#fff400}#mermaid-svg-iI4jX4lVJlJ4IL8h .section1,#mermaid-svg-iI4jX4lVJlJ4IL8h .section3{fill:#fff;opacity:0.2}#mermaid-svg-iI4jX4lVJlJ4IL8h .sectionTitle0{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .sectionTitle1{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .sectionTitle2{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .sectionTitle3{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-iI4jX4lVJlJ4IL8h .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .grid path{stroke-width:0}#mermaid-svg-iI4jX4lVJlJ4IL8h .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-iI4jX4lVJlJ4IL8h .task{stroke-width:2}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText:not([font-size]){font-size:11px}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-iI4jX4lVJlJ4IL8h .task.clickable{cursor:pointer}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText0,#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText1,#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText2,#mermaid-svg-iI4jX4lVJlJ4IL8h .taskText3{fill:#fff}#mermaid-svg-iI4jX4lVJlJ4IL8h .task0,#mermaid-svg-iI4jX4lVJlJ4IL8h .task1,#mermaid-svg-iI4jX4lVJlJ4IL8h .task2,#mermaid-svg-iI4jX4lVJlJ4IL8h .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutside0,#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutside2{fill:#000}#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutside1,#mermaid-svg-iI4jX4lVJlJ4IL8h .taskTextOutside3{fill:#000}#mermaid-svg-iI4jX4lVJlJ4IL8h .active0,#mermaid-svg-iI4jX4lVJlJ4IL8h .active1,#mermaid-svg-iI4jX4lVJlJ4IL8h .active2,#mermaid-svg-iI4jX4lVJlJ4IL8h .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-iI4jX4lVJlJ4IL8h .activeText0,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeText1,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeText2,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeText3{fill:#000 !important}#mermaid-svg-iI4jX4lVJlJ4IL8h .done0,#mermaid-svg-iI4jX4lVJlJ4IL8h .done1,#mermaid-svg-iI4jX4lVJlJ4IL8h .done2,#mermaid-svg-iI4jX4lVJlJ4IL8h .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-iI4jX4lVJlJ4IL8h .doneText0,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneText1,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneText2,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneText3{fill:#000 !important}#mermaid-svg-iI4jX4lVJlJ4IL8h .crit0,#mermaid-svg-iI4jX4lVJlJ4IL8h .crit1,#mermaid-svg-iI4jX4lVJlJ4IL8h .crit2,#mermaid-svg-iI4jX4lVJlJ4IL8h .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCrit0,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCrit1,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCrit2,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCrit0,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCrit1,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCrit2,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-iI4jX4lVJlJ4IL8h .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-iI4jX4lVJlJ4IL8h .milestoneText{font-style:italic}#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCritText0,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCritText1,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCritText2,#mermaid-svg-iI4jX4lVJlJ4IL8h .doneCritText3{fill:#000 !important}#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCritText0,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCritText1,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCritText2,#mermaid-svg-iI4jX4lVJlJ4IL8h .activeCritText3{fill:#000 !important}#mermaid-svg-iI4jX4lVJlJ4IL8h .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-iI4jX4lVJlJ4IL8h g.classGroup text .title{font-weight:bolder}#mermaid-svg-iI4jX4lVJlJ4IL8h g.clickable{cursor:pointer}#mermaid-svg-iI4jX4lVJlJ4IL8h g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-iI4jX4lVJlJ4IL8h g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-iI4jX4lVJlJ4IL8h .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-iI4jX4lVJlJ4IL8h .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .dashed-line{stroke-dasharray:3}#mermaid-svg-iI4jX4lVJlJ4IL8h #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h .commit-id,#mermaid-svg-iI4jX4lVJlJ4IL8h .commit-msg,#mermaid-svg-iI4jX4lVJlJ4IL8h .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-iI4jX4lVJlJ4IL8h g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-iI4jX4lVJlJ4IL8h g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-iI4jX4lVJlJ4IL8h g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-iI4jX4lVJlJ4IL8h .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-iI4jX4lVJlJ4IL8h .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-iI4jX4lVJlJ4IL8h .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-iI4jX4lVJlJ4IL8h .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-iI4jX4lVJlJ4IL8h .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-iI4jX4lVJlJ4IL8h .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-iI4jX4lVJlJ4IL8h .edgeLabel text{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iI4jX4lVJlJ4IL8h .node circle.state-start{fill:black;stroke:black}#mermaid-svg-iI4jX4lVJlJ4IL8h .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-iI4jX4lVJlJ4IL8h #statediagram-barbEnd{fill:#9370db}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-state .divider{stroke:#9370db}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-iI4jX4lVJlJ4IL8h .note-edge{stroke-dasharray:5}#mermaid-svg-iI4jX4lVJlJ4IL8h .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-iI4jX4lVJlJ4IL8h .error-icon{fill:#522}#mermaid-svg-iI4jX4lVJlJ4IL8h .error-text{fill:#522;stroke:#522}#mermaid-svg-iI4jX4lVJlJ4IL8h .edge-thickness-normal{stroke-width:2px}#mermaid-svg-iI4jX4lVJlJ4IL8h .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-iI4jX4lVJlJ4IL8h .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-iI4jX4lVJlJ4IL8h .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-iI4jX4lVJlJ4IL8h .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-iI4jX4lVJlJ4IL8h .marker{fill:#333}#mermaid-svg-iI4jX4lVJlJ4IL8h .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-iI4jX4lVJlJ4IL8h {color: rgba(0, 0, 0, 0.75);font: ;}

构建序列化对象的结构体
由结构体创建对象
序列化得到 XML 格式字符串
写入 .xml 文件

其中,有一个重要的细节,.xml 文件开头有一个头: <?xml version="1.0"?>。这个头在序列化的结果中是没有的,所以得自己写入。

以下为完整代码:

package mainimport ("encoding/xml""log""os"
)// library 对象同在 main 包下,详情见上文
func main() {// 输出为当前项目目录下的 library.xmlWriteXML("./library.xml", &library)
}func WriteXML(filePath string, ref interface{}) {// 序列化data, err := xml.MarshalIndent(ref, "", "\t")if err != nil {log.Println("文件序列化错误")}// 拼接 xml 文件头到 xml 字符串前data = append([]byte("<?xml version=\"1.0\"?>\n"), data ...)// 写出文件err = os.WriteFile(filePath, data, 0666)if err != nil {log.Println("文件写入错误")}
}

测试运行后在项目目录下出现 library.xml 并查看,发现 XML 的头也接上了,内容也没有问题。


二. XML 的反序列化

1. 反序列化的简单示例

以上文简单序列化过程中得到的字符串来进行反序列化测试。代码如下:

package mainimport ("encoding/xml""fmt""log"
)func main() {// 准备接受反序列化的空对象var library Library// 反序列化的 xml 字符串xmlStr := "<?xml version=\"1.0\"?><Library><name>广东大图书馆</name><location>广东</location>" +"<isPrivate>false</isPrivate><score>4.6</score><date>" +"<open>2021-07-08T18:26:33.7720883+08:00</open>" +"<close>2021-07-08T18:26:33.7720883+08:00</close></date>" +"<bookInfo><number>1005</number><book><name>Go 语言 JSON 序列化与反序列化</name>" +"<author>fxtack</author><publishTime>2021-07-08T18:26:33.7720883+08:00</publishTime>" +"</book><book><name>Go 语言 XML 序列化与反序列化</name><author>fxtack</author><publishTime>" +"2021-07-08T18:26:33.7720883+08:00</publishTime></book></bookInfo></Library>"// 反序列化err := xml.Unmarshal([]byte(xmlStr), &library)if err != nil {log.Println("反序列化失败")}fmt.Println(library)
}

输出如下,可见反序列化成功。

{广东大图书馆 广东 false 4.6 {2021-07-08 18:26:33.7720883 +0800 CST 2021-07-08 18:26:33.7720883 +0800 CST} {1005 [{Go 语言 JSON 序列化与反序列化 fxtack 2021-07-08 18:26:33.7720883 +0800 CST} {Go 语言 XML 序列化与反序列化 fxtack 2021-07-08 18:26:33.7720883 +0800 CST}]}}

注意


反序列化的函数 xml.Unmarshal 和序列化的函数不同,其传入的第二个参数必须是用于接受结果的结构体对象的地址。即,如下代码第一段是正确的,第二段是错误的。

...
// 正确
err := xml.Unmarshal([]byte(xmlStr), &library)
...
...
// 错误,会产生 err
err := xml.Unmarshal([]byte(xmlStr), library)
...

2. 反序列化的完整代码

反序列化的完整代码要读取 .xml 文件,将读取的内容进行反序列化,得到一个对象。流程如下:

#mermaid-svg-Ox9RhFhUNn5ZzfYF .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .label text{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .node rect,#mermaid-svg-Ox9RhFhUNn5ZzfYF .node circle,#mermaid-svg-Ox9RhFhUNn5ZzfYF .node ellipse,#mermaid-svg-Ox9RhFhUNn5ZzfYF .node polygon,#mermaid-svg-Ox9RhFhUNn5ZzfYF .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .node .label{text-align:center;fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .node.clickable{cursor:pointer}#mermaid-svg-Ox9RhFhUNn5ZzfYF .arrowheadPath{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .flowchart-link{stroke:#333;fill:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edgeLabel rect{opacity:0.9}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edgeLabel span{color:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .cluster text{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-Ox9RhFhUNn5ZzfYF .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-Ox9RhFhUNn5ZzfYF text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .actor-line{stroke:grey}#mermaid-svg-Ox9RhFhUNn5ZzfYF .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sequenceNumber{fill:#fff}#mermaid-svg-Ox9RhFhUNn5ZzfYF #sequencenumber{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF #crosshead path{fill:#333;stroke:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .messageText{fill:#333;stroke:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-Ox9RhFhUNn5ZzfYF .labelText,#mermaid-svg-Ox9RhFhUNn5ZzfYF .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .loopText,#mermaid-svg-Ox9RhFhUNn5ZzfYF .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-Ox9RhFhUNn5ZzfYF .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-Ox9RhFhUNn5ZzfYF .noteText,#mermaid-svg-Ox9RhFhUNn5ZzfYF .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-Ox9RhFhUNn5ZzfYF .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .section{stroke:none;opacity:0.2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .section2{fill:#fff400}#mermaid-svg-Ox9RhFhUNn5ZzfYF .section1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .section3{fill:#fff;opacity:0.2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sectionTitle0{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sectionTitle1{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sectionTitle2{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sectionTitle3{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-Ox9RhFhUNn5ZzfYF .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .grid path{stroke-width:0}#mermaid-svg-Ox9RhFhUNn5ZzfYF .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .task{stroke-width:2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText:not([font-size]){font-size:11px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .task.clickable{cursor:pointer}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskText3{fill:#fff}#mermaid-svg-Ox9RhFhUNn5ZzfYF .task0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .task1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .task2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutside0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutside2{fill:#000}#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutside1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .taskTextOutside3{fill:#000}#mermaid-svg-Ox9RhFhUNn5ZzfYF .active0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .active1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .active2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeText0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeText1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeText2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeText3{fill:#000 !important}#mermaid-svg-Ox9RhFhUNn5ZzfYF .done0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .done1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .done2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneText0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneText1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneText2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneText3{fill:#000 !important}#mermaid-svg-Ox9RhFhUNn5ZzfYF .crit0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .crit1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .crit2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCrit0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCrit1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCrit2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCrit0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCrit1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCrit2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-Ox9RhFhUNn5ZzfYF .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .milestoneText{font-style:italic}#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCritText0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCritText1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCritText2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .doneCritText3{fill:#000 !important}#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCritText0,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCritText1,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCritText2,#mermaid-svg-Ox9RhFhUNn5ZzfYF .activeCritText3{fill:#000 !important}#mermaid-svg-Ox9RhFhUNn5ZzfYF .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.classGroup text .title{font-weight:bolder}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.clickable{cursor:pointer}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-Ox9RhFhUNn5ZzfYF .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .dashed-line{stroke-dasharray:3}#mermaid-svg-Ox9RhFhUNn5ZzfYF #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF .commit-id,#mermaid-svg-Ox9RhFhUNn5ZzfYF .commit-msg,#mermaid-svg-Ox9RhFhUNn5ZzfYF .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-Ox9RhFhUNn5ZzfYF g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-Ox9RhFhUNn5ZzfYF .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-Ox9RhFhUNn5ZzfYF .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-Ox9RhFhUNn5ZzfYF .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edgeLabel text{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Ox9RhFhUNn5ZzfYF .node circle.state-start{fill:black;stroke:black}#mermaid-svg-Ox9RhFhUNn5ZzfYF .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-Ox9RhFhUNn5ZzfYF #statediagram-barbEnd{fill:#9370db}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-state .divider{stroke:#9370db}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-Ox9RhFhUNn5ZzfYF .note-edge{stroke-dasharray:5}#mermaid-svg-Ox9RhFhUNn5ZzfYF .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-Ox9RhFhUNn5ZzfYF .error-icon{fill:#522}#mermaid-svg-Ox9RhFhUNn5ZzfYF .error-text{fill:#522;stroke:#522}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edge-thickness-normal{stroke-width:2px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-Ox9RhFhUNn5ZzfYF .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-Ox9RhFhUNn5ZzfYF .marker{fill:#333}#mermaid-svg-Ox9RhFhUNn5ZzfYF .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-Ox9RhFhUNn5ZzfYF {color: rgba(0, 0, 0, 0.75);font: ;}

读取 .xml 文件得到 XML 字符串
创建可寻址的结构体对象实例
反序列化并由对象实例接收结果
使用对象实例

注意,序列化过程中要添加 XML 文件头,那反序列化过程中要不要专门处理 XML 文件头呢?答案不用,Go 反序列化过程会自动忽略 XML 文件头。

使用上文序列化产生的 library.xml 进行反序列化。

package mainimport ("encoding/xml""fmt""log""os"
)func main() {// 用于接收结果var library LibraryReadXML("./library.xml", &library)fmt.Println(library)
}func ReadXML(filePath string, ref interface{}) {// 读取文件f, err := os.ReadFile(filePath)if err != nil {log.Println("读取错误")return}// 反序列化err = xml.Unmarshal(f, ref)if err != nil {log.Println("反序列化失败")return}
}

输出结果如下,反序列化成功。

{Shanghai library Shanghai false 4.6 {2020-07-31 14:27:10.035542 +0800 CST 2020-07-31 14:27:10.035542 +0800 CST} {1005 [{Go 语言 JSON 序列化与反序列化 fxtack 2021-07-08 19:13:06.6253163 +0800 CST} {Go 语言 XML 序列化与反序列化 fxtack 2021-07-08 19:13:06.6253163 +0800 CST}]}}

三. Go 语言下 JSON 与 XML 序列化反序列化性能测试

JSON 格式和 XML 格式都可以用于对象的序列化与反序列化,但是其各有优劣。以下列举了一些公认的优缺点。

JSON XML
优点 格式简单,易于读写与解析。传输占用带宽相对小,信噪比高。多语言支持。 可以用 .dtd 或 xml Schema 规范编辑格式。数据表示方式更为多样。方便传输
缺点 相对 xml 规范性弱。 信噪比低。解析速度比 JSON 慢,解析更复杂。

提示


Go 中 JSON 的序列化与反序列化可以参照上一篇博客【Golang】Go 语言 JSON 的序列化与反序列化实践

对于同样的 Go 对象,我们对其进行 JSON 序列化与反序列化,和 XML 序列化与反序列化。简单的比较一下两者的性能高低。写了两个基准测试:

序列化基准测试:

package performanceimport ("encoding/json""encoding/xml""log""os""testing"
)func Benchmark_TestJSONMarshal(b *testing.B) {var data []bytefor i := 0 ; i < b.N ; i++ {data, _ = json.Marshal(library)}err := os.WriteFile("./library2.json", data, 0666)if err != nil {log.Println("文件写入错误")}
}func Benchmark_TestXMLMarshal(b *testing.B) {var data []bytefor i := 0 ; i < b.N ; i++ {data, _ = xml.Marshal(library)}err := os.WriteFile("./library2.xml", data, 0666)if err != nil {log.Println("文件写入错误")}
}

反序列基准测试:

package performanceimport ("encoding/json""encoding/xml""log""os""testing"
)func Benchmark_TestJSONUnmarshal(b *testing.B) {var ref Libraryf, err := os.ReadFile("./library.json")if err != nil {log.Println("读取错误")return}for i := 0 ; i < b.N ; i++ {_ = json.Unmarshal(f, &ref)}
}func Benchmark_TestXMLUnmarshal(b *testing.B) {var ref Libraryf, err := os.ReadFile("./library.xml")if err != nil {log.Println("读取错误")return}for i := 0 ; i < b.N ; i++ {_ = xml.Unmarshal(f, &ref)}
}

两个测试中用的 Library 结构体以及结构体对象都是同一个如下:

package performanceimport "time"type Library struct {Name      string      `xml:"name",json:"name"`Location  string      `xml:"location",json:"location"`IsPrivate bool        `xml:"isPrivate",json:"isPrivate"`Score     float64   `xml:"score",json:"score"`Date      Date      `xml:"date",json:"date"`BookInfo  BookInfo    `xml:"bookInfo",json:"bookInfo"`}type Date struct {Open   time.Time   `xml:"open",json:"open"`Close     time.Time   `xml:"close",json:"close"`
}type BookInfo struct {Number       int     `xml:"number",json:"number"`BookList  []Book  `xml:"book",json:"bookList"`
}type Book struct {Name         string      `xml:"name",json:"name"`Author        string      `xml:"author",json:"author"`PublishTime   time.Time   `xml:"publishTime",json:"publishTime"`
}var library = Library{Name:      "大大大图书馆",Location:  "广东",IsPrivate: false,Score:     5.0,Date: Date{Open:  time.Now(),Close: time.Now(),},BookInfo: BookInfo{Number: 1005,BookList: []Book{{Name: "Go 语言 JSON 序列化与反序列化",Author: "fxtack",PublishTime: time.Now(),},{Name:        "Go 语言 XML 序列化与反序列化",Author:      "fxtack",PublishTime: time.Now(),},{Name:        "Go 语言序列化与反序列化",Author:      "fxtack",PublishTime: time.Now(),},},},
}

在 performance 包下,启动控制台输入以下指令启动 Go 基准测试。

$ go test -v -bench=. -benchmem

测试结果如下:

Benchmark_TestJSONMarshal 测试方法的执行为例进行解释

  • Benchmark_TestJSONMarshal-12 中的 12 表示 12 个线程执行
  • 68574 表示测试循环执行了 68574 次
  • 17389 ns/op 表示平均每次执行耗时为 17389 纳秒
  • 3782 B/op 表示平均每次执行使用内存 3782 B
  • 22 allocs/op 表示每次执行分配了多少个对象

我们可以明显的看到 JSON 无论序列化还是反序列化,其执行速度都比 XML 的序列化与反序列化快,内存消耗少。

并且我们也可以发现,反序列化比序列化性能消耗更高。


四. 使用 io 流进行反序列化与序列化

假想,我们需要对一个大 XML 文件进行反序列化。该文件过大,无法一次性读取到内存中进行反序列化,那应该怎么办呢?Go 语言中提供了针对 io 流的序列化与方序类化函数。

以下示例展示了如何使用 io.Reader 来进行反序列化。

package mainimport ("encoding/xml""log""os"
)func main() {// 以只读模式打开大 XML 文件file, err := os.OpenFile("library.xml", os.O_RDONLY, 0777)if err != nil {log.Fatalln(err)}// 结果接收对象var lib Library// 使用 io.Reader 创建 decoder decoder := xml.NewDecoder(file)// 使用 decoder 进行反序列化err = decoder.Decode(&lib)if err != nil {log.Fatalln(err)}
}

提示


Go 中需要对 HTTP 请求的 body 内容进行反序列化时,就常常使用以上方法。这样可以避免 body 过大,从而减少内存占用。

相似的,如果对一个巨大的对象进行序列化,其序列化后的内容可能会过大而导致内存溢出,则可以使用 io.Writer 来进行序列化。

以下示例展示了如何使用 io.Writer 来进行序列化。

package mainimport ("encoding/xml""log""os"
)func main() {// 以只写模式打开当前目录下的 XML 大文件file, err := os.OpenFile("library.xml", os.O_WRONLY, 0777)if err != nil {log.Fatalln(err)}// 使用 io.Writer 创建 encoderencoder := xml.NewEncoder(file)// 使用 encoder 进行序列化err = encoder.Encode(&library)if err != nil {log.Fatalln(err)}
}

以下示例展示了如何使用 io.Writer 进行规范序列化。

package mainimport ("encoding/xml""log""os"
)func main() {file, err := os.OpenFile("hello.xml", os.O_WRONLY, 0777)if err != nil {log.Fatalln(err)}encoder := xml.NewEncoder(file)// 该语句进行规范化设置// 相当于设置 xml.MarshalIndent(&library, "", "\t") 中的后两个参数encoder.Indent(" ", "\t")err = encoder.Encode(&library)if err != nil {log.Fatalln(err)}
}

其他相关文章

文章名称 更新时间
Go 语言 JSON 的序列化与反序列化实践 2021-9-27
Go 语言 XML 的序列化与反序列化实践 2021-7-08

文章内容来自个人学习总结 欢迎指出本文中存在的问题 未经本人同意禁止转载,不得用于商业用途

【Golang】Go 语言 XML 的序列与反序列化实践相关推荐

  1. c语言xml序列化,C# XML和实体类之间相互转换(序列化和反序列化)

    我们需要在XML与实体类,DataTable,List之间进行转换,下面是XmlUtil类,该类来自网络并稍加修改. using System; using System.Collections.Ge ...

  2. XML的序列化和反序列化 详细介绍

    为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...

  3. jackson (json、xml的序列化与反序列化)

    jackson用于java对象到json的序列化与反序列化.还支持xml格式. jackson用于实现json与java对象的序列与反序列化.web service要实现跨机器传送对象那么就需要有一种 ...

  4. c++语言 xml数据绑定技术简介

    The C++ Source An Introduction to XML Data Binding in C++ by Boris Kolpackov May 4, 2007 原文:http://w ...

  5. 真分数c语言,C语言列出真分数序列代码及解析

    原标题:C语言列出真分数序列代码及解析 按递增顺序依次列出所有分母为60,分子小于60的最简分数. 分子.分母只有公因数1的分数叫做最简分数或者说分子和分母是互质数的分数,叫做最简分数,又称既约分数, ...

  6. “可扩展标记语言”(XML) 提供一种描述结构化数据的方法。

    摘要: "可扩展标记语言"(XML) 提供一种描述结构化数据的方法.与主要用于控制数据的显示和外观的 HTML 标记不同,XML 标记用于定义数据本身的结构和数据类型. XML 使 ...

  7. r语言 xmlto html,R语言XML文件

    XML是万维网上使用标准ASCII文本,内部网和其他地方共享文件格式和数据的文件格式. 它代表可扩展标记语言(XML). 与HTML类似,它包含标记标签.但与标记标签描述页面结构的HTML不同,标记标 ...

  8. R语言XML格式数据导入与处理

    数据解析 XML是一种可扩展标记语言,它被设计用来传输和存储数据.XML是各种应用程序之间进行数据传输的最常用的工具.它与Access,Oracle和SQL Server等数据库不同,数据库提供了更强 ...

  9. golang go语言_在7小时内学习快速简单的Go编程语言(Golang)

    golang go语言 The Go programming language (also called Golang) was developed by Google to improve prog ...

最新文章

  1. UIbutton系统按键(System)和图片按键(Custom)对比
  2. JoSE:球面上的词向量和句向量
  3. SDK,NDK,ADT工具下载常用地址
  4. android逆透视变换坐标,android – 如何使用OpenGL模拟OpenCV的warpPerspective功能(透视变换)...
  5. Windows C盘格式化或者同平台迁移oracle数据库
  6. RACCommand
  7. Barrett And Montgomery of Polynomials
  8. Python使用pyodbc访问数据库操作方法详解
  9. Obsidian media extended以及bilibili插件链接总是打开外部网页以及退回编辑视图会弹出另外一个相同文件
  10. DICOM MPPS的原理及应用
  11. SQLite实现获取本机短信数据
  12. 2015年中国数据库技术大会(DTCC)PPT合集
  13. HDU 1269 迷宫城堡 -- 强连通图判断
  14. 网易我的世界下的服务器目录在哪个文件夹,网易我的世界手机版存档导出在哪个文件夹 | 手游网游页游攻略大全...
  15. 用对象流把对象存到文件中,再从文件中读取出来打印。
  16. 发布坐标转换软件OpenCoord的使用第二集-椭球转换
  17. 点双连通分量 [HNOI2012]矿场搭建
  18. sql语句——创建临时表
  19. 总是被当成精神病的植物神经紊乱
  20. 【快手API】根据ID取商品详情 API 返回值说明

热门文章

  1. python中nomodulenamed怎么解决_python:ModuleNotFoundError:Nomodulenamed解决方法
  2. [转载] MATLAB快捷键
  3. 天猫多个商品主图、属性图和细节图分类下载
  4. 语音信号处理之(二)基音周期估计(Pitch Detection)
  5. 【网络】VLAN 及其配置详解
  6. Win10不进行操作很快自动睡眠、休眠的解决方法
  7. 【每日蓝桥】7、一三年省赛Java组真题“核桃的数量”
  8. Java清空文件内容
  9. 保卫萝卜迅玩版53关php,2018微信保卫萝卜迅玩版第50关攻略
  10. 第一章 接口测试基础