Go语言基础之结构体(秋日篇)

开发 后端
本篇我们学习Go基础之结构体的匿名字段结构体,结构体嵌套,匿名结构体嵌套,匿名嵌套结构体字段冲突。

[[354630]]

 前言

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) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

第8行和第9行代码,如果去掉注释会报错。

这就说明了个问题,如果是匿名字段结构体,匿名字段类型是不能重复的,如上述代码所示。

结构体嵌套

结构体嵌套,就如名字一样,一个结构体,嵌套了另外一个结构体。

假设

一个学生的信息,假设有姓名,年龄,性别,这三个字段。

这个学生必定要归属一个班级的,假设这个班级的信息有年级,几班,班主任姓名。

创建结构体

根据上述叙述,我们知道一定是有两个结构体的,至少一个是学生,一个是班级。

班级结构体

type Classes struct { 
    Grade       int    //年级 
    Class       int    //班级 
    TeacherName string //班主任姓名 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

学生结构体

type Student struct { 
    Name   string  //姓名 
    Age    int     //年龄 
    Gender string  //性别 
    class  Classes //所属班级 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

可以看到第5行代码,结构体的字段类型直接是一个结构体,这就是结构体嵌套、

当一个结构体不能完整描述一个对象时,或者说本来就是独立的对象有关联时,就需要结构体嵌套。

嵌套结构体赋值

方式一,直接赋值嵌套结构体

func main() { 
    var s1 = Student{ 
        Name:   "张三", 
        Age:    18, 
        Gender: "男", 
        class: Classes{ 
            Grade:       2020, 
            Class:       1, 
            TeacherName: "张三的老师", 
        }, 

    fmt.Println(s1) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

方式二,分开赋值

func main() { 
    var c1 = Classes{ 
        Grade:       2020, 
        Class:       1, 
        TeacherName: "张三的老师", 

    var s2 = Student{ 
        Name:   "张三", 
        Age:    18, 
        Gender: "男", 
        class:  c1, 

    fmt.Println(s2) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

两次执行结果


其实方式一和方式二的本质是一样的,只不过是方式二将嵌套的结构体单独赋值了而已。

匿名嵌套字段

上述我们的Student结构体是这样写的。

type Student struct { 
    Name   string  //姓名 
    Age    int     //年龄 
    Gender string  //性别 
    class  Classes //所属班级 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

但是其实第5行代码的字段是可以省略的,就像这样。

type Student struct { 
    Name   string  //姓名 
    Age    int     //年龄 
    Gender string  //性别 
    Classes //所属班级 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

但是在赋值时,就要注意了,因为Student结构体已经没有字段名了,所以就不能使用上述的方式赋值了

需要这种。

func main() { 
    var s1 = Student{ 
        Name:   "张三", 
        Age:    18, 
        Gender: "男", 
        Classes: Classes{ 
            Grade:       2020, 
            Class:       1, 
            TeacherName: "张三的老师", 
    }, 
  } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

没错,第5行的字段名是Classes结构体名。

执行结果还是一样的。

 

补充

上述是直接通过定义变量时就直接赋值了。

其实不管是结构体,还是嵌套结构体,都还有一种方法,就是通过.的方式赋值,代码如下。

结构体嵌套

默认的结构体嵌套,结构体还是有字段名的。

type Student struct { 
  Name    string //姓名 
  Age     int    //年龄 
  Gender  string //性别 
  class Classes        //所属班级 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

所以赋值代码如下。

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) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

第6行代码开始,通过s1找到class这个字段,再根据class找到class具体对应的值进行赋值。

匿名嵌套字段

匿名嵌套字段是没有字段名的,是有一个字段类型。

type Student struct { 
  Name    string //姓名 
  Age     int    //年龄 
  Gender  string //性别 
  Classes        //所属班级 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

所以赋值跟上述也不太一样,是这样的。

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) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

通过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) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

第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         //任课老师 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

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) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

第8行,直接找TeacherName字段,这时候就会出问题了。

 

意思很简单,就是不知道是Classes的TeacherName还是Course的TeacherName。

这时候,就必须要指定了。

s1.Classes.TeacherName = "张三的班主任" 
s1.Course.TeacherName = "张三的任课老师" 
  • 1.
  • 2.

总结

个人建议,还是尽量不要使用匿名嵌套结构体。

如果使用了匿名嵌套结构体,尽可能的采用标准方式赋值,不要采用懒得方式。

如果采用了懒的方式,一定要注意有没有字段冲突。

最后的总结

上述我们学习了Go基础之结构体的匿名字段结构体,结构体嵌套,匿名结构体嵌套,匿名嵌套结构体字段冲突。

各位小伙伴一定要实践一下,亲手打一下代码,坚持就是胜利,奥里给!

 

责任编辑:姜华 来源: Go语言进阶学习
相关推荐

2020-12-02 08:45:36

Go语言

2020-11-26 06:40:24

Go语言基础

2020-11-23 08:54:14

Go语言结构体

2020-12-20 09:59:13

Go语言基础技术

2020-12-02 09:10:22

Go结构数据类型

2023-07-29 15:03:29

2021-04-20 09:00:48

Go 语言结构体type

2022-02-16 10:03:06

对象接口代码

2020-11-05 09:58:16

Go语言Map

2020-12-16 08:07:28

语言基础反射

2020-12-23 08:39:11

Go语言基础技术

2020-11-11 10:52:54

Go语言C语言

2020-10-22 08:33:22

Go语言

2021-06-09 09:06:52

Go语言算法

2021-02-06 18:19:54

TimeGo语言

2022-04-27 10:01:43

切片Go封装

2020-12-27 10:15:44

Go语言channel管道

2021-10-09 07:10:31

Go语言基础

2020-12-30 09:04:32

Go语言TCPUDP

2020-10-23 08:38:19

Go语言
点赞
收藏

51CTO技术栈公众号