结构体
数组可以存储同一类的数据,但在结构体中,我们可以为不同项定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体的定义格式:
type 类型名 struct {
成员属性1 类型1
成员属性2 类型2
成员属性3 成员属性4 类型3
...
}
类型名,表示结构体的名称,在同一个包内不能重复。
结构体中的属性,也叫字段必须唯一。
同类型的成员属性可以写在一行。
type teacher struct {
name string
age int8
sex byte
}
结构体的定义只是一种内存布局的描述,只有当结构体实例化了,才会真正分配内存。
必须在实例化后才能使用结构体。
实例化就是根据结构体定义的格式创建一份与格式一致的内存区域。
结构体实例之间的内存是完全独立的。
先声明一个print函数,方便输入后面的代码。
func printTeacher(t teacher) {
fmt.Printf("姓名:%v,年龄:%d,性别%v \n", t.name, t.age, t.sex)
}
声明一个结构体,并打印信息。
var t0 teacher
printTeacher(t0)
var格式声明方式实例化结构体。
var t1 teacher
t1.name = "t1"
t1.age = 30
t1.sex = 0
printTeacher(t1)
短变量声明格式实例化结构体。
t2 := teacher{}
t2.name = "t2"
t2.age = 35
t2.sex = 1
printTeacher(t2)
用简短声明格式实例化结构体,并初始化。
t3 := teacher{
"t3",
40,
1,
}
printTeacher(t3)
t4 := teacher{"t4", 50, 0}
printTeacher(t4)
创建指针类型的结构体:
使用内置函数new()对结构体进行实例化,结构体实例化后形成的指针类型的结构体。
new函数会分配内存,第一个采纳数是类型,而不是值,返回的值是指向该类型新分配的零值指针。
盖函数用于创建某个类型的指针。
t5 := new(teacher)
//标准写法
(*t5).name = "t5"
(*t5).age = 55
//简化写法(语法糖)
t5.sex = 1
printTeacher(*t5)
结构体是一个值类型:
func testNewClass2() {
t1 := teacher{"t1", 21, 1}
fmt.Printf("t1 : %T , %v , %p \n", t1, t1, &t1)
fmt.Println("--------------")
t2 := t1
t2.name = "t2"
t2.age = 22
fmt.Printf("t1 : %T , %v , %p \n", t2, t2, &t2)
fmt.Printf("t1 : %T , %v , %p \n", t1, t1, &t1)
}
结构体是一个值类型,属于深拷贝,可以引用结构体的地址来进行浅拷贝。
func testClass3() {
t1 := teacher{"t1", 10, 1}
fmt.Printf("t1的姓名:%v,t1的年龄:%v,t1的性别:%v \n", t1.name, t1.age, t1.sex)
//深拷贝
t2 := t1
t2.name = "t2"
t2.age = 20
t2.sex = 0
fmt.Printf("t2的姓名:%v,t2的年龄:%v,t2的性别:%v \n", t2.name, t2.age, t2.sex)
fmt.Printf("修改t2后t1的姓名:%v,t1的年龄:%v,t1的性别:%v \n", t1.name, t1.age, t1.sex)
fmt.Println("---------------------------------")
//浅拷贝
t3 := &t1
t3.name = "t3"
t3.age = 30
t3.sex = 0
fmt.Printf("t2的姓名:%v,t2的年龄:%v,t2的性别:%v \n", t3.name, t3.age, t3.sex)
fmt.Printf("修改t2后t1的姓名:%v,t1的年龄:%v,t1的性别:%v \n", t1.name, t1.age, t1.sex)
fmt.Println("---------------------------------")
}
将结构体作为函数参数
func testClass4(t teacher) {
t.name = "修改以后"
t.age = 99
t.sex = 0
printTeacher(t)
}
将结构体指针作为函数参数
func testClass5(t *teacher) {
t.name = "修改以后"
t.age = 99
t.sex = 0
printTeacher(*t)
}
将结构体作为返回值
func testClass6(t teacher) teacher {
t.name = "修改以后"
t.age = 99
t.sex = 0
return t
}
将结构体指针作为返回值
func testClass7(t teacher) *teacher {
t.name = "修改以后"
t.age = 99
t.sex = 0
return &t
}
匿名结构体
没有名字的结构体。
无需通过type关键字定义就能直接使用。
在创建匿名结构体时,同时需要创建对象。
匿名结构体由结构体定义和兼职对初始化两个部分组成。
一般情况下匿名结构体仅仅只使用1次。
语法格式:
变量名 := struct {
定义成员属性
} { 初始化成员属性 }
匿名结构体示例:
func anonymousStruct1() {
addr := struct {
province, city string
}{"HuBei", "WuHan"}
fmt.Println(addr) //{HuBei WuHan}
}
匿名字段
结构体中的字段没有名字,只包含一个没有字段名的类型。
如果字段没有名字,那么默认使用类型作为字段名。
同一个类型只能写一个,局限性比较强。
结构体嵌套中采用的匿名结构体字段可以模拟继承关系。
匿名字段示例:
type cat struct {
string
int8
byte
}
func anonymousVariables1() {
c1 := cat{"mimi", 5, 0}
fmt.Println(c1)
//分别输出
fmt.Printf("名字:%v , 年龄:%v ,性别:%v \n", c1.string, c1.int8, c1.byte)
}