前言
Hey,大家好呀,码农我是星期八,咱们接着上次继续说,看一下结构体还有什么其他操作。没来得及上车的小伙伴请戳:Go语言基础之结构体(春日篇)、Go语言基础之结构体(夏日篇)。
匿名字段结构体
如果以后再遇到匿名这个词,就把他当作没有名字的意思。
匿名加字段结构体代码。
- package main
- import "fmt"
- type Student struct {
- string
- int
- //string //error:duplicate field string
- //int //error:duplicate field string
- }
- func main() {
- var s1 = Student{
- "666",
- 0,
- }
- fmt.Println(s1)
- }
第8行和第9行代码,如果去掉注释会报错。
这就说明了个问题,如果是匿名字段结构体,匿名字段类型是不能重复的,如上述代码所示。
结构体嵌套
结构体嵌套,就如名字一样,一个结构体,嵌套了另外一个结构体。
假设
一个学生的信息,假设有姓名,年龄,性别,这三个字段。
这个学生必定要归属一个班级的,假设这个班级的信息有年级,几班,班主任姓名。
创建结构体
根据上述叙述,我们知道一定是有两个结构体的,至少一个是学生,一个是班级。
班级结构体
- type Classes struct {
- Grade int //年级
- Class int //班级
- TeacherName string //班主任姓名
- }
学生结构体
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- class Classes //所属班级
- }
可以看到第5行代码,结构体的字段类型直接是一个结构体,这就是结构体嵌套、
当一个结构体不能完整描述一个对象时,或者说本来就是独立的对象有关联时,就需要结构体嵌套。
嵌套结构体赋值
方式一,直接赋值嵌套结构体
- func main() {
- var s1 = Student{
- Name: "张三",
- Age: 18,
- Gender: "男",
- class: Classes{
- Grade: 2020,
- Class: 1,
- TeacherName: "张三的老师",
- },
- }
- fmt.Println(s1)
- }
方式二,分开赋值
- func main() {
- var c1 = Classes{
- Grade: 2020,
- Class: 1,
- TeacherName: "张三的老师",
- }
- var s2 = Student{
- Name: "张三",
- Age: 18,
- Gender: "男",
- class: c1,
- }
- fmt.Println(s2)
- }
两次执行结果
其实方式一和方式二的本质是一样的,只不过是方式二将嵌套的结构体单独赋值了而已。
匿名嵌套字段
上述我们的Student结构体是这样写的。
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- class Classes //所属班级
- }
但是其实第5行代码的字段是可以省略的,就像这样。
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- Classes //所属班级
- }
但是在赋值时,就要注意了,因为Student结构体已经没有字段名了,所以就不能使用上述的方式赋值了
需要这种。
- func main() {
- var s1 = Student{
- Name: "张三",
- Age: 18,
- Gender: "男",
- Classes: Classes{
- Grade: 2020,
- Class: 1,
- TeacherName: "张三的老师",
- },
- }
- }
没错,第5行的字段名是Classes结构体名。
执行结果还是一样的。
补充
上述是直接通过定义变量时就直接赋值了。
其实不管是结构体,还是嵌套结构体,都还有一种方法,就是通过.的方式赋值,代码如下。
结构体嵌套
默认的结构体嵌套,结构体还是有字段名的。
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- class Classes //所属班级
- }
所以赋值代码如下。
- func main() {
- var s1 Student
- s1.Name = "张三"
- s1.Age = 18
- s1.Gender = "男"
- s1.class.Grade = 2020
- s1.class.Class = 1
- s1.class.TeacherName = "张三的老师"
- fmt.Println(s1)
- }
第6行代码开始,通过s1找到class这个字段,再根据class找到class具体对应的值进行赋值。
匿名嵌套字段
匿名嵌套字段是没有字段名的,是有一个字段类型。
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- Classes //所属班级
- }
所以赋值跟上述也不太一样,是这样的。
- func main() {
- var s1 Student
- s1.Name = "张三"
- s1.Age = 18
- s1.Gender = "男"
- s1.Classes.Grade = 2020
- s1.Classes.Class = 1
- s1.Classes.TeacherName = "张三的老师"
- fmt.Println(s1)
- }
通过s1直接找到Classes这个结构体,再根据这个结构体找到里面具体的值,进行赋值。
其实跟定义变量时赋值相似。
但是终究执行结果,还是一样的,只是赋值形式不同。
结论
根据嵌套结构体和匿名嵌套结构体再赋值时可以发现。
如果嵌套结构体有字段名,通过字段名找具体的字段,进行赋值。
如果是嵌套结构体匿名字段,通过嵌套结构体的名字,找具体字段,进行赋值。
嵌套结构体字段冲突
这个冲突的问题,其实还是比较少见的,这个问题通常情况下,只会出现在匿名嵌套场景中。
还是上述的结构体,但是赋值可以是这样操作的。
- func main() {
- var s1 Student
- s1.Name = "张三"
- s1.Age = 18
- s1.Gender = "男"
- s1.Classes.Grade = 2020
- s1.Classes.Class = 1
- s1.Classes.TeacherName = "张三的老师"
- //######### 分割 ##########
- s1.Grade = 2020 //省去了Classes
- s1.Class = 1 //省去了Classes
- s1.TeacherName = "张三的老师" //省去了Classes
- fmt.Println(s1)
- }
第10行,直接通过s1.Grade赋值,其实是省去了一个Classes,但是这种操作,只有在匿名嵌套结构体中可以使用。
但是如果我将结构体改成这样子。
- //班级
- type Classes struct {
- Grade int //年级
- Class int //班级
- TeacherName string //班主任姓名
- }
- //课程
- type Course struct {
- CourseName string //课程名字
- TeacherName string //任课老师姓名
- }
- //学生
- type Student struct {
- Name string //姓名
- Age int //年龄
- Gender string //性别
- Classes //所属班级
- Course //任课老师
- }
Student结构体有两个匿名嵌套结构体,一个是Classes,一个是Course。
但是有一个字段,是冲突的,就是TeacherName,如果还是通过懒的方式赋值,会发生什么呢?
- func main() {
- var s1 Student
- s1.Name = "张三"
- s1.Age = 18
- s1.Gender = "男"
- s1.Grade = 2020
- s1.Class = 1
- s1.TeacherName = "张三的老师"
- fmt.Println(s1)
- }
第8行,直接找TeacherName字段,这时候就会出问题了。
意思很简单,就是不知道是Classes的TeacherName还是Course的TeacherName。
这时候,就必须要指定了。
- s1.Classes.TeacherName = "张三的班主任"
- s1.Course.TeacherName = "张三的任课老师"
总结
个人建议,还是尽量不要使用匿名嵌套结构体。
如果使用了匿名嵌套结构体,尽可能的采用标准方式赋值,不要采用懒得方式。
如果采用了懒的方式,一定要注意有没有字段冲突。
最后的总结
上述我们学习了Go基础之结构体的匿名字段结构体,结构体嵌套,匿名结构体嵌套,匿名嵌套结构体字段冲突。
各位小伙伴一定要实践一下,亲手打一下代码,坚持就是胜利,奥里给!