10-结构体
Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。
当我们想表示一些事物时,我们可以用基本数据类型表示其各项基本属性,通过结构体将其组合起来。在 Go 中可以通过 struct
实现面向对象。
定义
注意:结构体是值类型!!!
使用 type
和 struct
来定义结构体。
基本语法如下:
type structT struct {
field1 T
field2 T
...
}
structT
:标识只定义结构体名称,同一包内不能重复。
field
:结构的基本属性的名字,结构体中的字段名不能重复
T
:字段的具体类型
eg:
type person struct {
name string
age int8
city string
}
同类型字段可以写在一行
type person struct {
name, city string
age int8
}
通过以上代码,我们就可以得到一个 person
的自定义类型,它有 name
、age
、city
三个字段,表示人的姓名、年龄、城市三个属性。
这样就可以通过 person
这个结构体很方便的在程序中表示和存储人的信息了。
Go 内置的基本数据类型用来描述一个值,而结构体用来描述一组值,本质上是一种聚合型数据类型。
一个结构体就像 Java 中的一个类,不过 Java 中的类还有构造函数、方法等,这些 Go 的结构体一样可以实现,方式有些不同
实例化
只有当结构体实例化时,才会真正地分配内存。即必须实例化后才能使用结构体的字段。
结构体本身也是一种数据类型,我们可以像声明基本数据类型一样声明结构体
// 方式1
var identifier structT
identifier.field1 = value1
identifier.field2 = value2
...
identifier
:结构体实例名称
structT
:结构体类型
field
:结构体字段
方式1:基本实例化
type person struct {
name string
city string
age int8
}
func main() {
// 方式1
var p1 person
p1.city = "SWA"
p1.name = "Boii"
fmt.Printf("p1 = %v \n", p1) // p1 = {Boii 0 SWA}
fmt.Printf("p1 = %#v \n", p1) // p1 = main.person{name:"Boii", age:0, city:"SWA"}
}
仔细观察:
- 方式1声明以后逐一给每个字段赋值,可以结构体中定义字段时的顺序,没有赋值的字段默认为零值
- 方式2 和 方式3在赋值的时候需要所有字段都赋值,且需要按顺序。
- 通过
.
可以访问结构体中的字段,例如p1.city
.
方式2:new(T) 结构体指针
通过内置函数 new()
可以对结构体实例化,得到的是结构体指针,其各个字段都为零值。
type person struct {
name string
city string
age int8
}
func main() {
var p1 = new(person)
fmt.Printf("%T \n", p1) // *main.person
fmt.Printf("p1 = %#v \n", p1) // p1 = &main.person{name:"", age:0, city:""}
p1.name = "Boii"
fmt.Printf("p1 = %#v \n", p1) // p1 = &main.person{name:"Boii", age:0, city:""}
}
注意:Go 中的结构体指针可以直接使用.
来访问结构体成员。
p1.name = "Boii"
相当于 (*p1).name = "Boii"
,这是 Go 的语法糖。
方式3:&T{} 取结构体地址
使用 &
对结构体取地址操作相当于对该结构体类型进行了一次 new
实例化操作。
type person struct {
name string
city string
age int8
}
func main() {
var p2 = &person{
"Boii", 10, "SWA"}
fmt.Printf("%T \n", p2) // *main.person
fmt.Printf("p2 = %#v \n", p2) // p = &main.person{name:"Boii", age:10, city:"SWA"}
p3 := &person{
}
p3.name = "Candy"
p3.age = 10
p3.city = "SWA"
fmt.Printf("%T \n", p3) // *main.person
fmt.Printf("p3 = %#v \n", p3) // p = &main.person{name:"Candy", age:10, city:"SWA"}
}
所以:new(Type)
和 &Type{}
是等价的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wlq9mjvG-1613447299933)(IMG/20201122164056342_11482.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sHqaGqDN-1613447299939)(IMG/20201122164122020_21432.png)]
匿名结构体
在定义一些临时数据结构等场景下还可以使用匿名结构体。
func main() {
// 定义匿名结构体
// 字段之间用 分号 隔开
var user