结构体

结构体(struct) 是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。学过 C 或 C++ 的人都知道结构体,但在 Go 中,没有像 C++ 中的 class 类的概念,只有 struct 结构体的概念,所以也没有继承。

创建一个结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

type Student struct {
name string // 学生姓名
sno string // 学生学号
age int // 学生年龄
}

func main() {
stu1 := Student{
name: "jpc",
sno: "123456",
age: 21,
}

stu2 := Student{"jzw", "123123", 22}

fmt.Println(stu1)
fmt.Println(stu2)

}

创建匿名结构体

  • 当定义好的结构体没有被显式初始化时,结构体的字段将会默认赋为相应类型的零值。
  • 点操作符 . 可以用于对结构体的字段的赋值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func main() {
stu := struct {
name string
sno string
age int
}{
name: "jhy",
sno: "222222",
age: 23,
}
stu.sno = "123321"
fmt.Println(stu)
}

匿名字段

在创建结构体时,字段可以只有类型没有字段名,这种字段称为 匿名字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

type Student struct {
string
int
}

func main() {
stu := Student{"jpc", 21}
fmt.Println(stu)
fmt.Println(stu.string)
fmt.Println(stu.int)
}

结构体嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import "fmt"

type Score struct {
math int
english int
}

type Student struct {
name string
sno string
score Score
}

// 结构体嵌套
func main() {

stu := Student{
name: "jpc",
sno: "123456",
}
stu.score = Score{98, 56}

fmt.Println(stu)
}

// 输出{jpc 123456 {98 56}}

提升字段

结构体中如果有匿名的结构体类型字段,则该匿名结构体里的字段就称为 提升字段(Promoted Fields) 。这是因为提升字段就像是属于外部结构体一样,可以用外部结构体直接访问。

对上面程序稍作修改:

1
2
3
4
5
type Student struct {
name string
sno string
Score
}

这样访问字段就可以从stu.score.math直接变成stu.math

结构体比较

结构体比较可以用==运算符可以用 DeeplyEqual()函数

给结构体定义方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import "fmt"

type Student struct {
name string
sno string
age int
}

//定义一个与 Student 绑定的方法
func (stu Student) Show() {
fmt.Println(stu.name)
fmt.Println(stu.sno)
fmt.Println(stu.age)
}


func (stu *Student) AddAge(n int) {
stu.age += n
}

func main() {
stu := Student{"jpc", "123456", 21}
stu.AddAge(3)
stu.Show()
}

结构体的 Tag 标签

Tag

Go语言结构体成员Tag来指定对应的JSON名字。

1
2
3
4
5
type Person struct {
Name string `json:"name"`
Target string `json:"target"`
Spend int `json:"spend,omitempty"`
}

Tagjson 对应值的第一部分用于指定 JSON 对象的名字,比如将 Go 语言中的 TotalCount 成员对应到 JSON 中的 total_count 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"encoding/json"
"fmt"
)

type People struct {
Name string `json:"name"`
Addr string `json:"addr"`
Age int `json:"age"`
}

func main() {
p1 := People{
Name: "谢老板",
Addr: "海底餐厅",
Age: 35,
}
// 结构体转化成json
data1, err := json.Marshal(p1)
if err != nil {
panic(err)
}
fmt.Printf("%s\n", data1)

}
// 输出
// {"name":"谢老板","addr":"海底餐厅","age":35}

Tag 获取

Tag 的格式上面已经说了,它是由反引号括起来的一系列用空格分隔的 key:"value" 键值对序列.

使用反射的方法获取 Tag 步骤如下:

  1. 获取字段
  2. 获取 Tag
  3. 获取键值对

其中获取字段有三种方式,而获取键值对有两种方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
"reflect"
)

type People struct {
Name string `json:"name"`
Addr string `json:"addr"`
Age int `json:"age"`
}

func main() {
p := reflect.TypeOf(People{})
name, _ := p.FieldByName("Name")
tag := name.Tag
fmt.Println("Name Tag:", tag)
keyValue, _ := tag.Lookup("json")
fmt.Println("key: json, value:", keyValue)
}