10 结构
结构
- Go 中的struct与C中的struct非常类似,并且Go没有class
- 使用Type(Name) struct{}定义结构,名称遵循可见性规则
- 支持指向自身的指针类型成员
- 支持匿名结构,可用作成员或者定义成员变量
- 匿名结构也可以用于map的值
- 可以使用字面值对结构进行初始化
- 允许直接通过指针来读写结构成员
- 相同类型的成员可以直接拷贝赋值
- 支持== 与 != 比较运算符,但不支持>或<
- 支持匿名字段,本质是定义了以某个类型名为名称的字段
- 嵌入结构作为匿名字段看起来像继承,但不是继承
- 可以使用匿名字段指针
struct的简单使用
我们先定义一个struct,然后在main函数里面使用它即可
type test struct {
Name string
Age int
}
func main() {
a := test{}
a.Name = "Leo" // 对Name这个进行赋值
a.Age = 22 // 对Age这个变量进行赋值
a := test{ // 也可以这样进行简单初始化,初始化的格式如下:
Name: "Leo ", // 变量名: 值,
}
fmt.Println(a)
}
struct 多层嵌套
所谓的多层嵌套就是struct里面再包含了一个struct,代码如下所示:
type person struct {
Name string
Age int
contact struct { // struct里面再包含了一个struct
Phone, City string
}
}
func main() {
a := person{Name: "joe", Age: 19}
a.contact.Phone = "182165234545" // 给里面那层struct赋值的时候只能这样做
a.contact.City = "Beijing"
fmt.Println(a)
}
struct 内存地址的拷贝
package main
import (
"fmt"
)
type test struct {
Name string
Age int
}
func main() {
a := test{
Name: "Leo ",
}
a.Age = 22
A(a)
fmt.Println(a) // 此时打印出来的结果还是22
}
func A(per test) {
per.Age = 19
fmt.Println("A", per)
}
// 打印结果如下:
A {Leo 19} // 值已经发生改变
{Leo 22} // 值没有发生改变
从上面的例子能够看出来,这个函数A的修改并没有影响main方法里面的值,所以可以得出这个修改实际上是test的一个内存拷贝,如果真正想在A里面修改值后影响到 main里面的值,就需要把内存地址传给A,那么就应该这么做,代码如下:
func main() {
a := test{
Name: "Leo ",
}
a.Age = 22
A(&a) // 加上&符合把内存地址传入
fmt.Println(a)
}
func A(per *test) { // 加上一个*号在test之前
per.Age = 19
fmt.Println("A", per)
}
那么问题来了,如果我有多个方法需要传入内存地址,那么该如何一次性让a等于内存地址呢?请看下面的代码
func main() {
a := &test{ // 提前把&放入到test之前
Name: "Leo ",
}
a.Age = 22
A(a)
B(a)
fmt.Println(a)
}
func A(per *test) { // 每个方法 的test前面添加一个*即可
per.Age = 19
fmt.Println("A", per)
}
func B(per *test) { // 每个方法 的test前面添加一个*即可
per.Age = 90
fmt.Println("B", per)
}
struct 匿名结构
匿名结构 的写法和js的自执行函数差不多,go的写法是 struct{}{}
func main() {
a := struct {
Name string
Age int
}{
Name: "joe",
Age: 19,
}
fmt.Println(a)
}
匿名结构
struct里面没有写变量名,只写了类型,所以赋值的时候只能照着顺序来
type person struct {
string
int
}
func main() {
a := person{"joe", 19}
fmt.Println(a)
}
struct 比较
两个struct之间比较的话,struct名字必须一样,如下所示
func main() {
a := person{"joe", 19}
b := person{"joe", 22}
fmt.Println(a == b) // 两个struct的名字一样才行
}
在struct继承情况下,如果有同名的变量会发生什么情况
话不多说,直接看代码:
import (
"fmt"
)
type human struct {
student
Name string
}
type student struct {
Name string
}
func main() {
b := human{Name: "hehe", student: student{Name: "Leo"}} // 变量同名了
fmt.Println(b.Name, b.student.Name)
}
// 打印结果
hehe Leo
由打印结果为导向,可以看出来,即使在继承struct的情况,有同名的也不会互相影响。
在struct继承情况下,父类没有的变量名而子类有会发生什么情况
话不多说,请看代码
import (
"fmt"
)
type human struct {
student
}
type student struct {
Name string
}
func main() {
b := human{student{Name: "Leo"}}
fmt.Println(b.Name, b.student.Name)
}
// 打印结果
Leo Leo
由打印结果为导向,可以看出来,如果父struct没有name的话,那么就会从子struct上取值