Golang学习 - 结构体(struct)
hanpy

Go 语言提供了结构体来定义复杂的数据类型。结构体是由一系列相同类型或不同类型的数据构成的数据集合。

定义和实例化

定义

结构体的定义使用关键字 typestruct 来进行

1
2
3
4
5
type 类型名称 struct {
field type
field type
field1,field2,field3 type // 同类型变量可以写在一行
}

需要注意几点

  1. 类型名在包内是唯一的
  2. 在同一个结构体中字段也是唯一的
  3. 相同类型的字段可以写在一行
  4. 实例化之后才能使用结构体的字段

实例化

1
2
3
4
5
type People struct {
Name string
Age int
Like []string
}

使用var

1
2
3
4
5
6
7
8
func main() {
var p People
p.Name = "hanpy"
p.Age = 30
p.Like = []string{"basketball"}
// 变量p,类型: main.People 值: {hanpy 30 [basketball]}
fmt.Printf("变量p,类型: %T 值: %v \n",p,p)
}

使用:=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func main()  {
// 1. 分开赋值
p1 := People{}
p1.Name = "zhangsan"
p1.Age = 20
p1.Like = []string{"basketball"}
// 变量p,类型: main.People 值: {zhangsan 20 [basketball]}
fmt.Printf("变量p,类型: %T 值: %v \n",p1,p1)

// 2. 直接赋值
p2:= People{
Name: "hanpy",
Age: 30,
Like: []string{"football"},
}
//变量p,类型: main.People 值: {hanpy 30 [football]}
fmt.Printf("变量p,类型: %T 值: %v \n",p2,p2)
}

new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main()  {
p := new(People)
fmt.Printf(" 变量p,类型: %T 值: %v \n",p,p)
// 给属性赋值
(*p).Name = "lisi"
(*p).Age = 20
(*p).Like = []string{"daze"}
fmt.Printf(" 变量p,类型: %T 值: %v \n",p,p)

// 语法糖写法
p.Name = "wangwu"
p.Age = 99
p.Like = []string{"sleep"}
fmt.Printf(" 变量p,类型: %T 值: %v \n",p,p)
}

匿名结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
func main()  {
// 声明初始化匿名结构体
p := struct {
Name string
Age int
Like []string
}{
Name: "zhaoliu",
Age: 40,
Like: []string{"eat"},
}
fmt.Printf(" 变量p,类型: %T 值: %v \n",p,p)
}

匿名字段

匿名字段就是在结构体中的字段没有名字,只包含一个没有字段名的类型。这些字段被称为匿名字段。在同一个结构体中,同一个类型只能有一个匿名字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type People struct {
Name string
int
}

func main() {
// 声明初始化匿名结构体
p := People{
Name: "zhangsan",
int: 20,
}
fmt.Printf("变量 p 的值: %v \n", p)
// 声明初始化匿名结构体(省略属性名)
p1 := People{"lisi", 19}
fmt.Printf("变量 p1 的值: %v \n", p1)
}
/*
变量 p 的值: {zhangsan 20}
变量 p1 的值: {lisi 19}
*/

结构体嵌套

把一个结构体作为另一个结构的字段,就是结构体嵌套。通过结构体嵌套可以模拟出来面向对象编程中的聚合关系继承关系

聚合关系

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
31
32
33
34
35
36
37
38
39
40
41
42
43
type Addr struct {
Province string
City string
Address string
}

type People struct {
Name string
Age int
AddrInfo Addr
}

func main() {
// 1. var
var p1 People
p1.Name = "zhangsan"
p1.Age = 20
p1.AddrInfo.Province = "河北"
p1.AddrInfo.City = "张家口"
p1.AddrInfo.Address = "河西街道"
// 1.1
// p1.AddrInfo = Addr{"河北", "张家口", "河西街道"}
// 1.2
//p1.AddrInfo = Addr{
// Province: "河北",
// City: "张家口",
// Address: "河西街道",
//}
fmt.Printf("变量 p1 的值: %v 类型: %T \n", p1, p1)

// 2. :=
addrInfo := Addr{"河北", "张家口", "河西街道"}
p2 := People{"lishi", 30, addrInfo}
fmt.Printf("变量 p2 的值: %v 类型: %T \n", p2, p2)

p3 := new(People)
p3.Name = "wangwu"
p3.Age = 40
p3.AddrInfo.Province = "河北"
p3.AddrInfo.City = "张家口"
p3.AddrInfo.Address = "河西街道"
fmt.Printf("变量 p3 的值: %v 类型: %T \n", p3, p3)
}

继承关系

在结构体中,属于匿名结构体的字段称为提升字段,它们可以被访问,匿名结构体就像是该结构体的父类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type People struct {
Name string
Age int
}

type Student struct {
People // 集成父类结构体
ClassName string
}

func main() {
s := Student{
People: People{"zhangsan", 30},
ClassName: "三年二班",
}
fmt.Println(s.ClassName) // 三年二班
}

成员冲突

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
type A struct {
Name string
Age int
}

type B struct {
Name string
}

type C struct {
A
B
}

func main() {
a := A{
Name: "A-Name",
Age: 1,
}
b := B{
Name: "B-Name",
}
c := C{
A: a,
B: b,
}
fmt.Println(c.Name)
}

// ambiguous selector c.Name