Go基础—5.结构体
一、Go结构体
结构体的基本定义和使用
结构体的定义格式如下:
ype 类型名 struct {
字段1 字段1类型
字段2 字段2类型
…
}
基本的实例化结构体
结构体本身是一种类型,可以像整型、字符串等类型一样,以 var 的方式声明结构体即可完成实例化。
【示例】代码如下所示:
package main
import "fmt"
type Point struct {
X,Y int
}
main() {
var p Point
p.X, p.Y = 1, 2
fmt.Println(p)
}
指针类型的结构体
Go语言中,还可以使用 new 关键字对类型(包括结构体、整型、浮点数、字符串等)进行实例化,结构体在实例化后会形成指针类型的结构体。
【示例】代码如下所示:
package main
import "fmt"
type Point struct {
X,Y int
}
main() {
p := new(Point)
p.X, p.Y = 11, 12
fmt.Println(*p)
}
结构体的地址实例化
在Go语言中,对结构体进行&取地址操作时,视为对该类型进行一次new()的实例化操作,取地址格式如下:
package main
import "fmt"
type Point struct {
X,Y int
}
main() {
p := &Point{}
p.X, p.Y = 11, 12
fmt.Println(*p)
}
初始化结构体的成员变量
使用多个值的列表初始化
书写格式如下:
ins := 结构体类型名{
字段1的值,
字段2的值,
......
}
下面的例子描述了一段地址结构,地址要求具有一定的顺序。
【示例】代码如下所示:
package main
import "fmt"
type PeopleInfo struct {
name string
age int
sex string
height float64
weight float64
}
func main() {
info := PeopleInfo{
"Jack",
23,
"男",
1.75,
120.56,
}
fmt.Println("个人信息:", info)
}
使用键值对初始化
书写格式如下:
ins := 结构体类型名{
字段1: 字段1的值,
字段2: 字段2的值,
......
}
下面的例子加了字段名,可以不用像上面的结构体一样按照顺序来。
【示例】代码如下所示:
package main
import "fmt"
type PeopleInfo struct {
name string
age int
sex string
height float64
weight float64
}
func main() {
info := PeopleInfo{
name: "Jack",
height: 1.75,
weight: 120.56,
age: 23,
sex: "男",
}
fmt.Println("个人信息:", info)
}
初始化匿名结构体
书写格式如下:
ins := struct {
// 匿名结构体字段定义
字段1 字段类型1
字段2 字段类型2
......
}{
// 字段值初始化
初始化字段1: 字段1的值,
初始化字段2: 字段2的值,
......
}
在下面示例中,使用匿名结构体的方式定义和初始化一个结构体,并调用函数打印出结构体的值。
【示例】代码如下所示:
package main
import "fmt"
func print_info(info *struct {
name string
age int
sex string
height float64
weight float64
}) {
// 使用动词%T打印info的类型
fmt.Printf("结构体的类型: %T\n", info)
// 打印info的数据信息
fmt.Println("结构体的数据:", *info)
}
func main() {
// 匿名初始化结构体
info := &struct {
name string
age int
sex string
height float64
weight float64
}{
name: "Jack",
height: 1.75,
weight: 120.56,
age: 23,
sex: "男",
}
// 使用print_info()传入结构体数据打印数据
print_info(info)
}
/* 运行结果如下
结构体的类型: *struct { name string; age int; sex string; height float64; weight float64 }
结构体的数据: {Jack 23 男 1.75 120.56}
*/
构造函数
模拟构造函数重载
使用结构体来描述猫的种类和颜色特征,可以通过下面方式来实现:
type Cat struct {
Color string
Name string
}
func NewCatByName(name string) *Cat {
return &Cat{
Name: name,
}
}
func NewCatByColor(color string) *Cat {
return &Cat{
Color: color,
}
}
模拟父级构造调用
在基类的结构体中嵌入一个一个结构体,类似面向对象的"派生"。
package main
import "fmt"
type Cat struct {
Color string
Name string
}
type WhiteCat struct {
Cat // 嵌入Cat, 类似于派生
}
// “构造基类”
func NewCat(name string) *Cat {
return &Cat{
Name: name,
}
}
// “构造子类”
func NewCatByColor(color string) *WhiteCat {
cat := &WhiteCat{}
cat.Color = color
return cat
}
func main() {
fmt.Println(NewCat("Casey"))
fmt.Println(NewCatByColor("white"))
}
/* 运行结果如下
&{ Casey}
&{{white }}
*/
结构体内嵌
结构体内嵌特性:
- 内嵌的结构体可以直接访问其成员变量。
嵌入结构体的成员,可以通过外部结构体的实例直接访问。如果结构体有多层嵌入结构体,结构体实例访问任意一级的嵌入结构体成员时都只用给出字段名,而无须像传统结构体字段一样,通过一层层的结构体字段访问到最终的字段。例如,ins.a.b.c的访问可以简化为ins.c。 - 内嵌结构体的字段名是它的类型名。
注意:嵌入结构体内部可能拥有相同的成员名,这样程序在编译的过程中会报错,编译器无法决定将值赋值给哪个结构体里的相同的成员名,所以在结构体里不能存在相同名字的字段。
【示例】代码如下所示:
package main
import "fmt"
type Variety struct {
v1, v2, v3, v4 string
}
type Prices struct {
sphynx int
ragdoll int
persian int
siamese int
}
// 将Variety和Prices结构体嵌入其中
type Cats struct {
name string
quantity int
Variety
Prices
}
func main() {
cat := Cats{}
// 对结构体里面的字段进行赋值
cat.name = "miaomi"
cat.quantity = 123
cat.v1 = "sphynx"
cat.v2 = "ragdoll"
cat.v3 = "persian"
cat.v4 = "siamese"
cat.sphynx = 800
cat.ragdoll = 1300
cat.persian = 4700
cat.siamese = 2300
// 打印出第一次赋值整个结构体的结果
fmt.Println(cat)
// 使用结构体字面量
cat2 := Cats{"xixi", 89, Variety{"sphynx", "ragdoll", "persian", "siamese"}, Prices{800, 1300, 4700, 2300}}
// 打印出第二次赋值整个结构体的结果
fmt.Println(cat2)
// 分开打印出结构体Cats里面内嵌结构体和本身的字段的值
fmt.Printf("cat2.name: %s, cat2.v1: %s, cat2.sphynx: %d", cat2.name, cat2.v1, cat2.sphynx)
}
/* 运行结果如下
{miaomi 123 {sphynx ragdoll persian siamese} {800 1300 4700 2300}}
{xixi 89 {sphynx ragdoll persian siamese} {800 1300 4700 2300}}
cat2.name: xixi, cat2.v1: sphynx, cat2.sphynx: 800
*/
初始化内嵌结构体
结构体内嵌初始化时,将结构体内嵌的类型作为字段名像普通结构体一样进行初始化。
【示例】代码如下所示:
package main
import "fmt"
type Variety struct {
v1, v2, v3, v4 string
}
type Prices struct {
sphynx int
ragdoll int
persian int
siamese int
}
type Cats struct {
name string
quantity int
Variety
Prices
}
func main() {
cat := Cats{
name: "miaomi",
quantity: 123,
Variety: Variety{
v1: "sphynx",
v2: "ragdoll",
v3: "persian",
v4: "siamese",
},
Prices: Prices{
sphynx: 800,
ragdoll: 1300,
persian: 4700,
siamese: 2300,
},
}
// 打印出cat的结构
fmt.Printf("%+v\n", cat)
// 打印出cat的值
fmt.Println(cat)
}
/* 运行结果如下
{name:miaomi quantity:123 Variety:{v1:sphynx v2:ragdoll v3:persian v4:siamese} Prices:{sphynx:800 ragdoll:1300 persian:4700 siamese:2300}}
{miaomi 123 {sphynx ragdoll persian siamese} {800 1300 4700 2300}}
*/