根据上面的图,我们发现学生类(结构体),讲师类(结构体)等都有共同的成员(属性和方法),这样就存在重复,所以我们把这些重复的成员封装到一个父类(结构体)中。然后让学生类(结构体)和讲师类(结构体)继承父类(结构体)
接下来,我们可以先将公共的属性,封装到父类(结构体)中实现继承,关于方法(函数)的继承后面再讲。

(1.1)匿名字段创建与初始化

那么怎样实现属性的继承呢?
可以通过匿名字段(也叫匿名组合)来实现,什么是匿名字段呢?通过如下使用,大家就明白了。
2.png
以上代码通过匿名字段实现了继承,将公共的属性封装在Person中,在Student中直接包含Person,那么Student中就有了Person中所有的成员,Person就是匿名字段。注意:Person匿名字段,只有类型,没有名字。
那么接下来说我们就可以给Student赋值了,具体初始化的方式如下:
3.png
以上代码中创建了一个结构体变量s1, 这个s1我们可以理解为就是Student对象,但是要注意语法格式,以下的写法是错误的:
var s2 Student=Student{101,”mike”,18,98.5}
其它初始化方式如下:
(1)自动推导类型
4.png
(2)指定初始化成员
5.png
接下来还可以对Person中指定的成员进行初始化。
6.png

(1.2)成员操作

创建完成对象后,可以根据对象来操作对应成员属性,是通过“.”运算符来完成操作的。具体案例如下:
7.png
由于Student继承了Person,所以Person具有的成员,Student也有,所以根据Student创建出的对象可以直接对age成员项进行修改。
由于在Student中添加了匿名字段Person,所以对象s1,也可以通过匿名字段Person来获取age,进行修改。
当然也可以进行如下修改:
8.png
直接给对象s1中的Person成员(匿名字段)赋值
通过以上案例我们可以总结出,根据类(结构体)可以创建出很多的对象,这些对象的成员(属性)是一样的,但是成员(属性)的值是可以完全不一样的。

(1.3)同名字段

现在将Student结构体与Person结构体,进行如下的修改:
9.png
在Student中也加入了一个成员name,这样与Person重名了,那么如下代码是给Student中name赋值还是给Person中的name 进行赋值?
10.png
输出的结果如下:
11.png
通过结果发现是对Student中的name进行赋值,所以在操作同名字段时,有一个基本的原则:如果能够在自己对象所属的类(结构体)中找到对应的成员,那么直接进行操作,如果找不到就去对应的父类(结构体)中查找。这就是所谓的就近原则。

(1.4)指针类型匿名字段

结构体(类)中的匿名字段的类型,也可以是指针。
例如:
12.png
输出结果:
13.png
输出了结构体的地址。如果要取值,可以进行如下操作:
14.png
在定义对象s时,完成初始化,然后通过”.”的操作完成成员的操作。
但是,注意以下的写法是错误的:
15.png
大家可以思考一下,以上代码为什么会出错?
会出错,错误信息如下:
invalid memory address or nil pointer dereference
翻译成中文:无效的内存地址或nil指针引用
意思是Person没有指向任何的内存地址,那么其默认值为nil.
也就是指针类型匿名字段
Person没有指向任何一个结构体,所以对象s也就无法操作Person中的成员。
具体的解决办法如下:
16.png
new( )的作用是分配空间,new( )函数的参数是一个类型,这里为Person结构体类型,返回值为指针类型,所以赋值给Person,
这样
Person也就指向了结构体Person的内存