结构体
谈谈go设计思想
Go语言通过用自定义的方式形成新的类型。Go语言使用结构体和结构体成员来描述真实世界。
Go语言没有类的概念,也不支持类的继承等面向对象思想。Go语言的结构体内嵌配合接口比面向对象具有更高的扩展性和灵活性。
Go语言不仅认为结构体能拥有方法,且每种自定义类型也可以拥有自己的方法。 ### 结构体的作用
结构体可以用来声明新的类型,作为其他类型的属性/字段的容器,如下定义一个学生结构体: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20type Student struct {
name string
age int
}
//按顺序初始化:每个成员都必须初始化
var s1 Student = Student{"lisi", 20}
//制定成员初始化:没有被初始化的,自动赋零值
s2 := Student{age:30}
//new 申请结构体
s3 := new(Student) //被new生成的结构体实例其实是指针类型
s3.name = "zs" //这里的.语法只是语法糖,将s3.name转换成了(*s3).name
s3.age = 27
//直接声明
var s4 Student
s4.name = "ww"
s4.age = 30
struct的结构中的类型可以是任意类型,且存储空间是连续的,其字段按照声明时的顺序存放。 如果结构体的所有的成员都是可以比较的,那么结构体本身也是可以比较的,使用 == != ,不支持 > 和 <。 注意:如果结构体的成员要被包外调用,需要大写首字母。
取结构体地址与实例化
前面说过,对结构体的new其实是生成了一个指针类型。其实对结构体进行&
取地址操作时,也可以视为对该类型进行一次new
的实例化操作。
1 | ins := &T{} |
匿名字段
struct的字段名与类型一一对应,如果不提供名字,则为匿名字段。
如果匿名字段是一个struct时,这个struct拥有的全部字段都被隐式引入了当前的struct。
1 | type Human struct { |
不仅仅是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
25
26
27
28
29
30
31type Human struct {
name string
age int
weight int
}
type Student struct {
Human // 匿名字段,struct
Skills // 匿名字段,自定义的类型string slice
int // 内置类型作为匿名字段
speciality string
}
func main() {
// 初始化学生Jane
jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"}
// 现在我们来访问相应的字段
fmt.Println("Her name is ", jane.name)
fmt.Println("Her age is ", jane.age)
fmt.Println("Her weight is ", jane.weight)
fmt.Println("Her speciality is ", jane.speciality)
// 我们来修改他的skill技能字段
jane.Skills = []string{"anatomy"}
fmt.Println("Her skills are ", jane.Skills)
fmt.Println("She acquired two new ones ")
jane.Skills = append(jane.Skills, "physics", "golang")
fmt.Println("Her skills now are ", jane.Skills)
// 修改匿名内置类型字段
jane.int = 3
fmt.Println("Her preferred number is", jane.int)
}
这里有一个问题:如果human里面有一个字段叫做phone,而student也有一个字段叫做phone,那么该怎么办呢? Go里面很简单的解决了这个问题,最外层的优先访问,也就是当你通过student.phone访问的时候,是访问student里面的字段,而不是human里面的字段。
内嵌结构体
当前结构体可以直接访问其内嵌结构体的内部字段: 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
41package main
import "fmt"
type Animal struct {
Age int
}
type Person struct {
Animal
Name string
}
type Student struct {
Person
ClassName string
}
func main() {
// 初始化方式1
s1 := Student{
Person{
Animal: Animal {
Age: 15,
},
Name:"lisi",
},
"一班",
}
fmt.Println(s1.Age) // 正确输出15
fmt.Println(s1.Person.Name) // 正确输出lisi
// 初始化方式2
var s2 Student
s2.Name = "zs"
s2.Age = 30
s2.ClassName = "二班"
fmt.Println(s2.Age) // 正确输出30
fmt.Println(s2.Person.Name) // 正确输出zs
}