GoLang结构体
基本使用
首先,给出结构体的一些理解。
结构体是一些属性的集合,这些属性可以称作为字段,在程序中其实就是一些变量。通过这些属性(字段)的组合来描述某一事物的特征。实际上,结构体就是对所要描述物质的抽象。
1. 定义结构体
type struct_name struct{
var_name1 type
var_name2 type
var_name3 type
.
.
.
var_namen type
}
2. 声明并初始化结构体对象
结构体示例:
type Animal struct{
name string
age int
sex boolean
}
- 方法一:声明结构体变量,然后通过
.
运算符访问赋值,进行初始化
var st1 Animal
st1.name = "猫"
st1.age = 3
st1. sex = false
println(st1.name)
println(st1.age)
println(st1.sex)
//结果为:
//猫
//3
//false
- 方法二:声明的同时使用
{}
进行初始化
var st1 Animal = Animal{
name: "猫",
age: 3,
sex: false, //这里最后一个逗号不能省略,如果要省略,那么右大括号应该位于这一行
}
//或者简写为如下形式
st2 := Animal{
name: "猫",
age: 3,
sex: false,
}
//或者简写为如下形式
st3 := Animal{ //使用这种形式时,赋值顺序与结构体中变量的声明顺序一致。
"猫",
3,
false,
}
- 方法三:使用
new()
函数:专门用来创建某种类型的指针的函数
st4 := new(Animal)
st4.name = "猫"
st4.age = 3
st4.sex = false
fmt.Printf("%p---%T", st4, st4)
//结果为:
//0xc0000593c0---*main.Person
从返回结果*main.Person
可以看出,使用new()
函数创建的结构体示例,返回的是一个结构体指针,它指向使用new()
函数开辟的空间。
同时,对于结构体指针,可以通过.
运算符直接访问其指向结构体的字段。
3. 值类型与引用数据类型
Golang语言中:
值类型:int, float, bool, string, array, struct
等
引用类型: slice, map ,function, pointer
等
- 针对于
struct
,其实例为值类型。当将一个结构体变量赋值给另外一个结构体变量时,会发生一次拷贝。比如:st1 := st2
,这里st2
事先已经初始化,那么会将st2
的值复制一份,然后放到st1
的内存空间中去。
示例:
var st2 Animal = Animal{
name: "猫",
age: 3,
sex: false,
}
st1 := st2
st1.name = "狗"
fmt.Println(st1)
fmt.Println(st2)
//结果为:
//{狗 3 false}
//{猫 3 false}
从上面这段代码可以看出,修改st1
并不会影响st2
的值。
示例:
var st2 *Animal = new(Animal)
st2.name = "猫"
st2.age = 3
st2.sex =false
st1 := st2
st1.name = "狗"
fmt.Println(st1)
fmt.Println(st2)
//结果为:
//&{狗 3 false}
//&{狗 3 false}
//0xc0000503c0---0xc0000503c0
可见,st1
和st2
都是结构体的引用,都指向同一内存空间。所以通过st1
或st2
修改结构体的字段,都会影响到另一方的值。
匿名结构体及匿名字段
- 匿名结构体
当我们需要使用一个结构体并声明其变量来使用时有两种做法。一种是先定义该结构体,然后声明其变量;另一种便是使用匿名结构体。使用匿名结构体,不需要使用type关键字指定结构体类型的名称。
使用语法:
struct{
field1 type
filed2 type
.
.
.
filedn type
}{
field1: value1,
field2: value2,
field3: valur3,
.
.
.
fieldn: valuen,
}
解析:第一个大括号中的内容,是对匿名结构体的字段定义。第二个大括号中的内容是对匿名结构体字段的初始化
使用示例:
animal := struct{
name string
age int
}{
name: "猫",
age: 3,
}
fmt.Println(animal)
//结果为:
{猫 3}
- 匿名结构体字段
对于结构体中的字段,有时可以省略其字段名。注:结构体中的变量也可以称其为字段。
示例:
type Animal struct{ string int }
声明一个
Animal
的结构体变量:var a Animal = Animal{"猫", 3}
如何访问没有字段名的结构体的字段呢?这种情况下,字段的类型默认被作为字段名处理。也就是说,字段的类型即起到数据类型的作用,也充当字段名的作用。
示例:
var a Animal = Animal{"猫", 3} fmt.Println(a.string, a.int) //结果为: //猫 3
- 根据上面所说,可以知道,结构体的匿名字段只有在当前结构体的字段类型不复杂时使用。即当结构体中出现多个同一类型的字段时,匿名字段就无法使用。因为匿名字段的类型充当字段标识符的作用,如果出现相同类型的匿名字段,那么无法确定是对哪个字段的访问。
示例:如下代码段,会让编译器报错
type Animal struct{ string int string //这里有了两个string类型的匿名字段,报错 }
结构体的嵌套
简单来说,结构体的定义中有另外一个结构体的定义,这就是结构体的嵌套。
何时使用呢?一般,当一个结构体的属性中拥有另外一个结构体时就会使用结构体的嵌套。
如下:
type Book struct{ //定义Book结构体,描述书的名称与价格
name string
price float64
}
type Student struct{ //定义student结构体,描述学生的姓名,年龄,与读过的书
name string
age int
book Book
}
参考资料
- https://www.bilibili.com/video/BV1jJ411c7s3?p=86&vd_source=008445eb63b17edad78a03ae3d20c08a
- https://www.runoob.com/go/go-structures.html