非零基础自学Golang
第9章 结构体
9.7 匿名结构体
9.7.1 匿名结构体定义与初始化
匿名结构体,顾名思义,即没有名字的结构体,与匿名函数类似。
匿名结构体无须type关键字就可以直接使用,匿名结构体在创建的同时也要创建对象。
匿名结构体的初始化和使用更加简单,无须通过type关键字定义,且不用写出类型名称。
匿名结构体在初始化时需进行匿名结构体定义和成员变量初始化(可选),格式如下:
title: Go语言
结构体实例 := struct{
//匿名结构体定义
成员变量1 类型1
成员变量2 类型2
成员变量3 类型3
...
}{
//成员变量初始化(可选)
成员变量1:值1,
成员变量2:值2,
成员变量3:值3,
...
}
[ 动手写9.7.1]
package main
import "fmt"
type Book struct {
title string
author string
num int
id int
}
func main() {
book1 := struct {
title string
author string
num int
id int
}{
title: "Go语言",
author: "Tom",
num: 20,
id: 152368,
}
fmt.Println("title: ", book1.title)
fmt.Println("author: ", book1.author)
fmt.Println("num: ", book1.num)
fmt.Println("id: ", book1.id)
}
运行结果
如果需要初始化多个不同的实例(书),那么会存在大量重复的代码。
所以,实际开发过程中,不建议通过这种方式来使用结构体。
9.7.2 匿名结构体的应用
匿名结构体一般可用于组织全局变量、构建数据模板和解析JSON等。
例如,我们可以通过自定义匿名结构体将同一类的全局变量组织在一起。
var config struct {
IP string
Port int
}
config.IP = "192.168.1.1"
config.Port = 8080
另外,我们经常会使用匿名结构体来临时存储经过解析后的JSON数据:
[ 动手写 9.7.2]
package main
import (
"encoding/json"
"fmt"
)
func main() {
data := &struct {
Code int
Msg string
}{}
jsonData := `{"code":200 ,"msg":""}`
if err := json.Unmarshal([]byte(jsonData), data); err != nil {
fmt.Println(err)
}
fmt.Println("code: ", data.Code)
fmt.Println("msg: ", data.Msg)
}
运行结果
在以上例子中,由于json包的Unmarshal函数的第二个参数为JSON解析后传递的对象,因此必须传入对象引用而非值传递。
9.8 小结
-
Go语言的结构体是一种对现实生活中实体的抽象,结构体由一系列成员变量构成,这些成
员变量对应着实体不同的属性。 -
定义结构体后,需要对结构体进行实例化才能使用结构体的字段。
Go语言实例化结构体主要有:
- 标准实例化
- new函数实例化
- 取地址实例化三种方式。
-
Go语言中可以通过键值对格式和列表格式对结构体进行初始化。
9.9 知识拓展
9.9.1 使用结构体解析XML文件
XML即可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
在计算机中,标记指计算机所能理解的信息符号,通过此类标记,计算机之间可以处理包含各种信息的文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。它是网络环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。
早在1998年,W3C就发布了XML 1.0规范,用来简化网络间的文档信息传输。
当然现在是 Json 独大了
XML本质上是一种树形的数据格式,我们可以定义与之匹配的Go语言的struct类型,然后通过xml包对XML文件中的数据进行解析,存储到自定义的结构体中。
我们先创建test.xml文件,文件内容如下,用于进行解析:
<?xml version="1.0" encoding="UTF-8" ?>
<Persons>
<Person>
<Name>小丁</Name>
<Age>23</Age>
<Interests>
<Interest>看书</Interest>
<Interest>打游戏</Interest>
</Interests>
</Person>
<Person>
<Name>凤凤</Name>
<Age>22</Age>
<Interests>
<Interest>姜云升</Interest>
<Interest>吃零食</Interest>
</Interests>
</Person>
</Persons>
根据XML文件中的内容,自定义结构体如下。必须注意的是,解析的时候,tag、字段名、XML元素都是对大小写敏感的,所以必须一一对应字段。
type Result struct {
Person []Person
}
type Person struct {
Name string
Age string
Interests Interests
}
type Interests struct {
Interest []string
}
使用ioutil包中的ReadFile方法,将源代码所在目录下的test.xml文件内容读入content变量,类型为字节数组类型:
content, err := ioutil.ReadFile("test.xml")
之后使用xml包中的Unmarshal方法解析XML文件内容:
err = xml.Unmarshal(content, res)
程序源代码如下,最后打印所解析的XML文件内容:
[ 动手写 9.9.1]
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
)
type Result struct {
Person []Person
}
type Person struct {
Name string
Age string
Interests Interests
}
type Interests struct {
Interest []string
}
func main() {
var res Result
content, err := ioutil.ReadFile("test.xml")
if err != nil {
fmt.Println(err)
return
}
err = xml.Unmarshal(content, &res)
if err != nil {
fmt.Println(err)
}
fmt.Println("XML文件解析后的内容为: ")
fmt.Println(res)
}
其实ioutil.ReadFile 这玩意儿已经弃用了
【今天是 2022 年12 月 4 日】
看看官方API 文档
果然是已经弃用了
看到可以换成OS
试试
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Result struct {
Person []Person
}
type Person struct {
Name string
Age string
Interests Interests
}
type Interests struct {
Interest []string
}
func main() {
var res Result
content, err := os.ReadFile("第9章结构体/知识拓展/test.xml")
if err != nil {
fmt.Println(err)
return
}
err = xml.Unmarshal(content, &res)
if err != nil {
fmt.Println(err)
}
fmt.Println("XML文件解析后的内容为: ")
fmt.Println(res)
}
运行结果
OK
Go语言中是利用反射机制将来自XML文件中的数据反射成对应的struct对象的,其中缺少的元素或空属性值将被解析为零值。