一、结构体
1.1 什么是结构体
Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
1.2 结构体的定义和初始化
type struct_variable_type struct {member definition;member definition;...member definition;}
一旦定义了结构体类型,它就能用于变量的声明
variable_name := structure_variable_type{value1, value2...valuen}
初始化结构体
// 1. 定义结构体type Person struct {name stringage intsex stringaddress string}func main() {// 初始化方法一var p1 Personfmt.Println(p1) // { 0 } 全是默认值p1.name = \"张三\"p1.age = 30p1.sex = \"男\"p1.address = \"成都\"fmt.Println(p1) // {张三 30 男 成都}fmt.Printf(\"姓名:%s,年龄:%d,性别:%s,地址:%s\\n\", p1.name, p1.age, p1.sex, p1.address)// 初始化方法二p2 := Person{}fmt.Println(p2) // { 0 } 全是默认值p2.name = \"张三\"p2.age = 30p2.sex = \"男\"p2.address = \"成都\"fmt.Println(p2) // {张三 30 男 成都}fmt.Printf(\"姓名:%s,年龄:%d,性别:%s,地址:%s\\n\", p2.name, p2.age, p2.sex, p2.address)// 初始化方法三p3 := Person{name: \"张三\",age: 30,sex: \"男\",address: \"成都\",}fmt.Println(p3) // {张三 30 男 成都}fmt.Printf(\"姓名:%s,年龄:%d,性别:%s,地址:%s\\n\", p3.name, p3.age, p3.sex, p3.address)// 初始化方法四p4 := Person{\"张三\",30,\"男\",\"成都\",}fmt.Println(p4) // {张三 30 男 成都}fmt.Printf(\"姓名:%s,年龄:%d,性别:%s,地址:%s\\n\", p4.name, p4.age, p4.sex, p4.address)}
1.3 值传递
结构体是值传递是深拷贝
通过指针可以完成引用传递
p5 := Person{name: \"张三\",age: 30,sex: \"男\",address: \"成都\",}p6 := p5fmt.Printf(\"%p,%T\\n\",&p5,p5) // 0xc00001c200,main.Personfmt.Printf(\"%p,%T\\n\",&p6,p6) // 0xc00001c240,main.Personp6.name = \"李四\"fmt.Println(p5) // {张三 30 男 成都}fmt.Println(p6) // {李四 30 男 成都}var pp1 *Personpp1 = &p5fmt.Println(pp1) // &{张三 30 男 成都}fmt.Printf(\"%p,%T\\n\",pp1,pp1) // 0xc00001c200,*main.Personfmt.Println(*pp1) // {张三 30 男 成都}pp1.name = \"王五\"fmt.Println(pp1) // &{王五 30 男 成都}fmt.Println(*pp1) // {王五 30 男 成都}fmt.Println(p5) // {王五 30 男 成都}
1.4 make、new
make、new操作
make用于内建类型(map、 slice 和channel)的内存分配。
new用于各种类型的内存分配
new 专门创建某种类型的指针,返回的指针并不是空指针,存的是默认值
内建函数new本质上说跟其它语言中的同名函数功能一样: new(T)分配了零值填充的T类型的内存空间,并且返回其地址,即一个*T类型的值。用Go的术语说,它返回了一个指针,指向新分配的类型T的零值。有一点非常重要: new返回指针
内建函数make(T, args)与new(T)有着不同的功能,make只能创建slice、map和channel,并且返回一个有初始值(非零)的T类型,而不是灯。本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个slice, 是一个包含指向数据(内部array) 的指针、长度和容量的三项描述符;在这些项目被初始化之前,slice为nil。 对于slice、map和channe|来说, make初始化 了内部的数据结构,填充适当的值。make返回初始化后的(非零) 值。
1.5 匿名结构体和匿名字段
匿名结构体:没有名字的结构体,在创建匿名结构体时,同时创建对象
匿名字段:一个结构体的字段没有字段名
// 匿名结构体s1 := struct {name stringage int}{name: \"李四\",age: 19,}fmt.Println(s1)// 匿名字段,使用类型名作为字段名,所以匿名字段不能出现2个类型一样的s2 := struct {stringint}{\"李四\",19,}fmt.Println(s2.string, s2.int)
1.6 结构体的嵌套
嵌套的结构体
一个结构体可能包含一个字段,而这个字段反过来就是一个结构体。 这些结构被称为嵌套结构。
// 1. 定义结构体type Student struct {name stringage intaddress Address}type Address struct {city stringstate string}func main() {s3 := Student{\"张三\",19,Address{\"成都\",\"四川\",},}fmt.Println(s3) // {张三 19 {成都 四川}}fmt.Println(s3.name,s3.age,s3.address) // 张三 19 {成都 四川}fmt.Println(s3.address.city,s3.address.state) // 成都 四川}
1.7 提升字段,模拟继承
Hummy就是提升字段,Address不是提升字段
访问
Hummy:s3.name // 就相当于继承父类属性(模拟继承)
Address:s3.address.city // 模拟聚合关系,不能直接访问Address中的属性
// 1. 定义结构体type Hummer struct {name stringage int}type Student struct {Hummeraddress Address}type Address struct {city stringstate string}func main() {s3 := Student{Hummer{\"张三\",19,},Address{\"成都\",\"四川\",},}fmt.Println(s3) // {张三 19 {成都 四川}}fmt.Println(s3.name,s3.age,s3.address) // 张三 19 {成都 四川}fmt.Println(s3.address.city,s3.address.state) // 成都 四川var s4 Students4.name = \"张三\"s4.age = 19s4.address.city = \"成都\"s4.address.state = \"四川\"fmt.Println(s4) // {张三 19 {成都 四川}}fmt.Println(s4.name,s4.age,s4.address) // 张三 19 {成都 四川}fmt.Println(s4.address.city,s4.address.state) // 成都 四川}