12-Go语言结构体

结构体

结构体的基本概念
  • 什么是结构体
    • Go语言中的结构体几乎和C语言中的结构体一模一样都需要先定义结构体类型, 再定义结构体变量都是用来保存一组不同类型数据的
    • 定义结构体类型格式:
      type 结构体类型名称 struct{
      属性名称 属性类型;
      属性名称 属性类型;
      }
    • 定义结构体变量格式: var 结构体变量名称 结构体类型名称

结构体初始化

注意点: 和切片以及字典不一样, 结构体变量定义之后就可以直接使用了

//1.定义一个结构体
    //1.1定义结构体类型
    type Person struct {
        name string
        age int
    }
    //1.2定义结构体变量(先定义后初始化)
    var per Person
    //1.3操作结构体
    //切片和字典定义变量后必须初始化才能使用
    //结构体变量定义完成后不需要初始化可以直接使用
    per.name = "lnj"
    per.age = 18
    fmt.Println(per)
  • 先定义结构体变量再初始化
//3.先定义结构体变量再初始化
    //定义结构体类型
    type Person struct {
        name string
        age int
    }
    //定义结构体变量
    var per Person
    //给结构体完全初始化
    per = Person{"wjh",19}
    //给结构体部分初始化
    //注意点: 部分初始化必须通过属性名称指定要给谁初始化
    per = Person{age : 18}
    fmt.Println(per)
  • 定义结构体变量的同时初始化
//2.定义结构体变量一次性初始化
    //定义一个结构体类型
    type Person struct {
        name string
        age int
    }
    //定义结构体变量一次性初始化
    var per Person = Person{"lnj",18}
    //结构体变量名称后面可以省略结构体类型
    var per = Person{"lnj",18}
    //可以使用语法糖来定义同时一次性初始化
    per := Person{"lnj",18}
    fmt.Println(per)

结构体值传递
package main

import "fmt"

//定义一个结构体
type Person struct {
    name string
    age int
}
func main() {
    /*
    结构体和数组一样,都是值传递
    作为函数的参数,在函数内部修改值不会影响到外面实参的值
    */

    per1 := Person{"wjh", 19}
    var per2 Person
    //将结构体变量per1的值传递给per2
    per2 = per1
    per2.name = "lnj"
    fmt.Println(per1)//{wjh 19}
    //修改结构体变量per2的值不会影响per1中的值
    fmt.Println(per2)//{lnj 19}

    per := Person{"lnj", 10}
    //结构体作为函数的参数,在函数内部修改值不会影响到外面实参的值
    change(per)
    fmt.Println(per)

}
func change(per Person)  {
    per.name = "haha"
}

复杂结构体
package main

import "fmt"

func main() {
    /*
    复杂的结构体
    */

    type Person struct {
        name string //字符串
        age int  //整型
        score float64 //浮点型
        arr [3]int //数组类型
        sce []int //切片类型
        dict map[string]string  //字典类型
    }

    //普通类型结构体属性都可以直接操作,不需要初始化
    var per Person
    per.name = "lnj"
    per.age = 18
    per.score = 80.5
    per.arr[0] = 10
    per.arr[1] = 20
    per.arr[2] = 30

    //{lnj 18 80.5 [10 20 30] [] map[]}

    //切片和字典类型的必须要先初始化才可以使用
    //创建切片
    //per.sce = []int{10,20,30}
    //注意点: 使用索引方式,不能超过切片的长度
    per.sce = make([]int,3)
    per.sce[0]= 10
    per.sce[1]= 20
    per.sce[2]= 30


    //创建字典
    per.dict = make(map[string]string,2)
    per.dict["name"] = "wjh"
    per.dict["age"] = "18"
    //per.dict = map[string]string{"name":"wjh","age" :"18"}
    fmt.Println(per)
}


结构体转换

注意点:结构体变量之间可以相互转换, 但是必须保证结构体类型的属性名称 属性类型 属性顺序 属性的个数 都一样

package main

import "fmt"

func main() {
    /*
    结构体变量之间可以相互转换, 但是必须保证结构体类型的
    属性名称 属性类型 属性顺序 属性的个数 都一样
    */

    type Person1 struct {
        name string
        age int
    }

    //属性顺序不同
    type Person2 struct {
        age int
        name string
    }
    //属性名称不同
    type Person3 struct {
        name string
        score int
    }
    //属性类型不同
    type Person4 struct {
        name string
        score float64
    }
    //属性的个数不同
    type Person5 struct {
        name string
        age int
        score float64
    }

    //属性顺序不同不能强转
    //var per2 Person2
    //per2 = Person1(per2)
    //fmt.Println(per2)


    //属性名称不同不能强转
    //var per3 Person3
    //per3 = Person1(per3)
    //fmt.Println(per3)

    //属性类型不同不能强转
    var per4 Person4
    per4 = Person1(per4)
    fmt.Println(per4)

    //属性个数不同不能强转
    var per5 Person5
    per5 = Person1(per5)
    fmt.Println(per5)
}


匿名结构体
  • 什么是匿名结构体属性?
    没有名称的属性就是匿名属性
  • 如何操作匿名属性?
    匿名属性的数据类型就是匿名属性的名称, 所以可以通过匿名属性的数据类型来操作
  • 匿名属性一般都用于结构体的嵌套定义,结构体的属性又是一个结构体
package main

import "fmt"

func main() {
    type Person struct {
        string //匿名结构体属性
        int
    }

    var per Person
    per.string = "wjh" //可以通过匿名属性的数据类型来操作
    per.int = 18
    fmt.Println(per)

    type Date struct {
        year int
        month int
        day int
    }

    type Person struct {
        name string
        age int
        Date //结构体嵌套定义

    }

    type Animal struct {
        name string
        age int
        Date
    }

    //使用结构体嵌套
    var per Person
    per.name = "wjh"
    per.age = 19
    per.Date = Date{2007,10,23} //{wjh 19 {2007 10 23}}
    fmt.Println(per)

    //定义结构体变量同时直接初始化
    ani := Animal{"wawa",10,Date{2003,10,23}}
    fmt.Println(ani)//{wawa 10 {2003 10 23}}
}

结构体嵌套的方式
  • 第一种方式(双重嵌套)
    type 结构体名称1 struct{

    }
    type 结构体名称2 struct{
    结构体名称1
    }

//1.第一种方式
    // 结构体和嵌套的结构体没有重名属性的情况
    type Person struct {
        name string
        age int
    }

    type Student struct {
        Person
        score float64
    }

    //定义同时初始化结构体
    stu := Student{Person{"wjh", 19}, 86.6}
    fmt.Println(stu)

    ////1.1结构体嵌套定义,第一种操作结构体方法
    //stu.Person.name = "lnj"
    //stu.Person.age = 30
    //fmt.Println(stu)

    //1.2第二种操作结构体方法
    //会先去Student结构体中查询有没有name属性, 如果有就直接访问
    //如果没有会继续查找嵌套的匿名结构体中有没有, 如果有就访问匿名结构体中的name属性
    stu.name = "zs" //嵌套结构体属性不重名可以直接访问
    stu.age = 20
    fmt.Println(stu)
    //2.第一种方式有重名属性的情况
    //结构体和嵌套的结构体有重名属性的情况
    type Person struct {
        name string
        age int
    }

    type Student struct {
        Person
        name string
        score float64
    }

    //定义同时初始化结构体
    stu := Student{Person{"wjh",19},"lnj", 90.3}
    fmt.Println(stu) //{{wjh 19} lnj 90.3}

    //2.1结构体嵌套定义,操作结构体的第一种方法
    //注意点: 如果结构体与嵌套的结构体属性有重名,使用这种方法操作数据,不会更改嵌套结构体中的同名属性
    stu.name = "haha"
    fmt.Println(stu) //{{wjh 19} haha 90.3}

    //2.2结构体嵌套定义,操作结构体第二种方法
    //注意点: 如果结构体与嵌套的结构体属性有重名,应该先指定结构体类型在指定结构体属性
    stu.Person.name = "zs"
    stu.age = 30
    fmt.Println(stu) //{{zs 30} haha 90.3}
  • 第二种方式(三重嵌套)
    type 结构体名称1 struct{
    }
    type 结构体名称2 struct{
    结构体名称1
    }
    type 结构体名称3 struct{
    结构体名称2
    }
//第二种方式
    //1.没有重名属性
    type Object struct {
        name string
    }
    type Person struct {
        Object
        age int
    }
    type Student struct {
        Person
        score float32
    }

    //定义变量同时初始化
    stu := Student{Person{Object{"wjh"}, 19}, 87.3}
    fmt.Println(stu) //{{{wjh} 19} 87.3}

    //操作结构体第一种方法
    stu.name = "zs"
    stu.age = 30
    stu.score = 50.3
    fmt.Println(stu) //{{{zs} 30} 50.3}

    //操作结构体第二种方法
    stu.Person.Object.name = "lnj"
    stu.Person.age = 50
    fmt.Println(stu) //{{{lnj} 50} 50.3}
//有重名属性的情况
    type Object struct {
        name string
    }
    type Person struct {
        Object
        name string
        age int
    }
    type Student struct {
        Person
        name string
        score float32
    }

    //定义变量同时初始化
    stu := Student{Person{Object{"wjh"},"lnj",13},"niuzi",39.2}
    fmt.Println(stu) //{{{wjh} lnj 13} niuzi 39.2}

    //操作结构体方法
    //注意点: 如果不先指定结构体类型,只会操作最外面结构体的对应的重名属性
    stu.name = "whaha" //修改Student结构体类型的name属性
    stu.Person.name = "zs"  //修改Person结构体类型的name属性
    stu.Person.Object.name = "lili"  //修改Object结构体类型的name属性
    fmt.Println(stu) //{{{lili} zs 13} whaha 39.2}
    
  • 第三种方式
    type 结构体名称1 struct{

    }
    type 结构体名称2 struct{
    }
    type 结构体名称3 struct{
    结构体名称1
    结构体名称2
    }

//第三种方式
    //没有重名属性情况
    type Object struct {
        name string
    }
    type Person struct {
        age int
    }
    type Student struct {
        Object
        Person
        score float64
    }

    //定义变量同时初始化
    stu := Student{Object{"lnj"},Person{19},30.6}
    fmt.Println(stu) //{{lnj} {19} 30.6}

    //操作结构体属性
    stu.Person.age = 30
    stu.Object.name = "wjh"
    fmt.Println(stu) //{{wjh} {30} 30.6}
    

    //有重名属性的情况
    type Object struct {
        name string
    }
    type Person struct {
        name string
        age int

    }
    type Student struct {
        Object
        Person
        name string
        score float64
    }

    stu := Student{Object{"haha"},Person{"lnj", 19},"wjh", 30.5}
    fmt.Println(stu)

    //操作结构体属性
    stu.name = "ll"
    stu.Person.name = "zz"
    stu.Object.name = "kk"
    fmt.Println(stu)

结构体嵌套定义注意点
  • 结构体的属性类型不能是当前结构体的类型(不能自己嵌套自己)
  • 只有匿名属性才会向上查找, 非匿名属性不会向上查找
package main

import "fmt"

func main() {
    /*
    1.结构体的嵌套定义的注意点:
    1.1结构体的属性类型不能是当前结构体的类型
    1.2只有匿名属性才会向上查找, 非匿名属性不会向上查找
    */

    type Person struct {
        //Person  结构体属性不能是自己本身的结构体类型
        name string
        age  int
    }

    type Student struct {
        //per Person //非匿名结构体属性
        Person //匿名结构体属性
        score float32
    }

    stu := Student{Person{"wjh", 18}, 52.3}
    fmt.Println(stu)
    //匿名结构体属性会自动往匿名结构体查找属性
    //非匿名结构体属性使用这种方法查找会报错
    fmt.Println(stu.name)
    fmt.Println(stu.age)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容