Go语言基础之结构体!
发表于更新于
编程语言GoGo语言基础之结构体!
月伴飞鱼
Go语言中的基本数据类型可以表示一些事物的基本属性
Go语言提供了一种自定义数据类型,可以封装多个基本数据类型
Go语言中通过struct
来实现面向对象。
结构体的定义
使用type
和struct
关键字来定义结构体。
1 2 3 4 5 6 7 8
| type 类型名 struct{ 字段名 字段类型 字段名 字段类型 ... }
|
1 2 3 4 5
| type person struct{ name string age int8 city string }
|
同类型的字段也可以写在一行。
1 2 3 4
| type person struct{ name,city string age int8 }
|
结构体实例化
只有当结构体实例化时,才会真正地分配内存,也就是必须实例化后才能使用结构体的字段。
结构体本身也是一种类型
- 可以像声明内置类型一样使用
var
关键字来声明结构体类型。
通过.
来访问结构体字段(成员变量),例如p.name
和p.age
等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var 结构体实例 结构体类型
type person struct { name string city string age int8 }
func main() { var p1 person p1.name = "娜扎" p1.city = "北京" p1.age = 18 fmt.Printf("p1=%v\n", p1) fmt.Printf("p1=%#v\n", p1) }
|
匿名结构体
在定义一些临时数据结构等常见下可以使用匿名结构体。
1 2 3 4 5 6 7 8 9 10 11 12
| package main import ( "fmt" ) func main() { var user struct{Name string; Age int} user.Name = "小王子" user.Age = 18 fmt.Printf("%#v\n", user) }
|
创建指针类型结构体
通过使用new
关键字对结构体进行实例化,得到的是结构体地址。
1 2 3
| var p = new(person) fmt.Printf("%T\n",p) fmt.Printf("p=%#v\n",p)
|
从打印结果来看,此时p
是一个结构体指针。
在Go语言中支持对结构体指针直接使用.
来访问结构体成员。
1 2 3 4 5
| var p = new(person) p.name = "Negan" p.age = 68 p.city = "亚历山大" fmt.Printf("p=%#v\n",p)
|
取结构体的地址实例化
使用&
对结构体进行取地址操作相当于对该结构体类型进行了一次new
实例化操作。
1 2 3 4 5 6 7
| p := &person{} fmt.Printf("%T\n",p) fmt.Printf("p=%v\n",p) p.name = "Negan" p.age = 68 p.city = "救世堂" fmt.Printf("p=%#v\n",p)
|
p.name="Negan"
其实在底层是(*p3).name="Negan"
结构体初始化
没有初始化的结构体,其成员变量都是对应其类型的零值。
1 2 3 4 5 6 7 8 9 10
| type person struct{ name string age int8 city string }
func main(){ var p person fmt.Printf("p=%#v\n",p) }
|
使用键值对初始化
使用键值对对结构体进行初始化,键对应结构体的字段,值对应该字段的初始值。
1 2 3 4 5 6
| p := person{ name:"Negan", age:68, city:"亚历山大" } fmt.Printf("p=%#v\n",p)
|
也可以使用结构体指针进行键值对初始化。
1 2 3 4 5 6
| p := &person{ name:"Negan", age:68, city:"亚历山大" } fmt.Printf("p=%#v\n",p)
|
当某些字段没有初始值的时候,该字段可以不写
- 此时没有指定初始值的字段的值就是该字段类型的零值。
1 2 3 4
| p := &person{ city:"救世堂" } fmt.Printf("p=%#v\n",p)
|
使用值的列表初始化
初始化结构体的时候可以简写,也就是初始化的时候不写键,直接写值。
使用这种格式初始化时,需要注意:
- 必须初始化结构体的所有字段
- 初始值的填充循序必须与字段在结构体中的声明顺序一致
- 该方式不能和键值初始化方式混用
1 2 3 4 5 6
| p := &person{ "Negan", 68, "救世堂" } fmt.Printf("p=%#v\n",p)
|
结构体的继承
Go语言中使用结构体可以实现其他编程语言中的面向对象继承。
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
| type Animal struct{ name string }
func (a *Animal) move(){ fmt.Printf("%s会动", a.name) }
type Dog struct { Feet int8 *Animal }
func (d *Dog) wang(){ fmt.Printf("%s会汪汪汪~\n",d.name) }
func main() { d := &Dog{ Feet: 4, Animal:&Animal{ name: "旺财", }, } d.wang() d.move() }
|
结构体字段的可见性
结构体中字段大写开头表示公开访问
嵌套结构体
一个结构体中可以嵌套包含另一个结构体或者结构体指针。
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
| type Address struct{ Province string City string }
type User struct{ Name string Gender string Address Address }
func main() { user := User{ Name: "Negan", Gender:"男", Address: Address{ Province: "陕西", City: "西安", }, } fmt.Printf("user=%#v\n", user) }
|
嵌套匿名结构体
当访问结构体成员时会现在结构体中查找该字段,找不到再去匿名结构体中查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| type Address struct { Province string City string }
type User struct{ Name string Gender string Address }
func main() { var user User user.Name = "Negan" user.Gender = "男" user.Address.Province = "陕西" user.City = "西安" fmt.Printf("user=%#v\n", user) }
|
嵌套结构体的字段名冲突
嵌套结构体内部可能存在相同的字段名
- 这个时候为了避免歧义需要制定具体的内嵌结构体的字段。
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
| type Address struct{ Province string City string CreateTime string }
type Email struct{ Account string CreateTime string }
type User struct { Name string Gender string Address Email }
func main() { var user User user.Name = "Negan" user.Gender = "男" user.Address.CreateTime = "2020" user.Email.CreateTime = "2020" fmt.Printf("%#v\n", user) }
|