13-GoLang结构体

栏目: Go · 发布时间: 7年前

内容简介:第一种方式: 没有重名属性的情况第一种方式: 有重名属性的情况第二种方式: 没有重名属性的情况

结构体

  • Go语言中的结构体几乎和 C语言 中的结构体一模一样

    都需要先定义结构体类型, 再定义结构体变量

    都是用来保存一组不同类型数据的

  • C语言定义结构体类型的格式

struct 结构体类型名称{
        属性名称 属性类型;
        属性名称 属性类型;
    }
  • Go语言定义结构体类型的格式
type 结构体类型名称 struct{
        属性名称 属性类型;
        属性名称 属性类型;
    }

  //定义一个结构体类型
    type Person struct{
        name string
        age int
    }
  • C语言中通过结构体类型定义结构体变量, 必须拷贝struct
    struct 结构体类型名称 结构体变量名称;
  • Go语言中通过结构体类型定义结构体变量, 不用拷贝struct
    var 结构体变量名称 结构体类型名称
//通过结构体类型定义结构变量
    var per Person
    per.name = "luo"
    per.age = 18
    fmt.Println(per)
  • 和C语言中的结构体一样, 可以定义结构体变量的同时初始化, 也可以先定义结构体变量再初始化
type Person struct{
        name string
        age int
    }
    // 定义的同时初始化
    var per Person = Person{"luo", 18}
    fmt.Println(per)

    // 先定义再初始化
    var per2 Person
    //per = Person{"luo", 18} // 完全初始化
    per2 = Person{name:"luo"} // 部分初始化, 必须通过属性名称指定要给谁初始化
    fmt.Println(per2)
  • 注意点:

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

    (若结构体中有slice map不能直接使用,见后文)

结构体和函数

  • 结构体类型和数组类型一样, 在 Go 语言中都是值传递,修改形参不会影响到实参
package main

import "fmt"

// 1.定义一个结构体类型
type Person struct {
    name string
    age int
}
func main() {
    // 2.定义一个结构体变量
    p1 := Person{"luo", 18}

    // 3.再定义一个结构体变量
    var p2 Person
    // 4.将p1赋值给p2
    p2 = p1
    // 5.修改p2的值
    fmt.Println(p1)  //{luo 18}
    p2.name = "zs"
    fmt.Println(p1)  //{luo 18}
    fmt.Println(p2)  //{zs 18}

    change(p1)
    fmt.Println(p1)  //{luo 18}
}

func change(pp Person)  {
    pp.name = "zs"
}

复杂结构体

  • 注意点: 如果结构体的属性是 切片和字典类型 , 那么就不能直接操作,必须先给切片初始化(创建切片)
package main

import (
    "fmt"
)

func main() {
    type Person struct {
        age int
        score float32
        name string
        arr [3]int
        sce []int
        dict map[string]string
    }

    var per Person
    // 常规的数据类型, 我们都可以直接操作, 完全没有问题
    per.age = 18
    per.score = 100
    per.name = "luo"
    per.arr[0] = 1
    per.arr[1] = 3
    per.arr[2] = 5
    fmt.Println(per)  //{18 100 luo [1 3 5] [] map[]}
    // 注意点: 如果结构体的属性是切片和字典类型, 那么就不能直接操作
    // 必须先给切片初始化(创建切片)
    per.sce = make([]int, 2)
    per.sce[0] = 123
    per.sce[1] = 456
    //per.sce[2] = 789 // 通过索引操作切片, 不能超出切片的长度
    fmt.Println(per)  //{18 100 luo [1 3 5] [123 456] map[]}

    per.dict = make(map[string]string)
    per.dict["name"] = "zs"
    fmt.Println(per)    //{18 100 luo [1 3 5] [123 456] map[name:zs]}
    
    //demo
    type LUO struct {
        name string
        age int
        score float64
        arr [3]int
        sce []int
        dict0 map[string]string
    }
    var luo LUO
    luo.name="lyw"
    luo.age = 0
    luo.score = 99.5
    luo.arr[0] = 1
    luo.arr[1] = 2
    luo.arr[2] = 3
    luo.sce = make([]int,2)
    luo.sce[0] = 111
    luo.sce[1] = 222
    luo.dict0 = make(map[string]string)
    luo.dict0["dog"] = "zjw"
    fmt.Println(luo)     //{lyw 0 99.5 [1 2 3] [111 222] map[dog:zjw]}
}

结构体之间的转换

  • 结构体变量之间可以相互转换, 但是必须保证结构体类型的

    属性名称 属性类型 属性顺序 属性的个数 都一样

package main

import "fmt"

func main() {
    type Person1 struct {
        name string
        age int
    }
    // 属性顺序不同
    type Person2 struct {
        age int
        name string
    }
    // 如果属性名称和类型都一样, 但是顺序不一样, 不能转换
    //var p1 Person1 = Person1{}
    //var p2 Person2
    //p2 = Person2(p1)
    //fmt.Println(p1)
    //fmt.Println(p2)

    type Person3 struct {
        name1 string
        age int
    }
    // 如果属性的类型和顺序都一样, 但是名称不一样, 不能转换
    //var p1 Person1 = Person1{}
    //var p2 Person3
    //p2 = Person3(p1)
    //fmt.Println(p1)
    //fmt.Println(p2)

    type Person4 struct {
        name string
        age int
        score int
    }
    // 如果属性的名称和类型都一样, 但是个数不一样, 不能转换
    //var p1 Person1 = Person1{}
    //var p2 Person4
    //p2 = Person4(p1)
    //fmt.Println(p1)
    //fmt.Println(p2)

    type Person5 struct {
        name [10]byte
        age int
    }
    // 如果属性名称和个数都一样, 但是属性数据类型不一样, 不能转换
    //var p1 Person1 = Person1{}
    //var p2 Person5
    //p2 = Person5(p1)
    //fmt.Println(p1)
    //fmt.Println(p2)

    type Person6 struct {
        name string
        age int
    }

    // 只有属性个数, 属性名称, 属性类型, 属性顺序都一样, 才能转换
    var p1 Person1 = Person1{"luo",18}
    var p2 Person6
    p2 = Person6(p1)
    fmt.Println(p1)  //{luo 18}
    fmt.Println(p2)  //{luo 18}
}

结构体匿名属性

  • 什么是匿名结构体属性?

    只有数据类型,没有名称的属性就是匿名属性

type Person struct {
        int // 只有数据类型, 没有名称, 就是匿名属性
        name string
    }
  • 如何操作匿名属性?

    匿名属性的数据类型就是匿名属性的名称, 所以可以通过匿名属性的数据类型来操作

type Person struct {
        int
        string
    }
    var per Person
    per.int = 18
    per.string = "luo"
    fmt.Println(per)
  • 匿名属性一般都用于结构体的嵌套定义

    结构体的属性又是一个结构体

type Date struct {
        year int
        month int
        day int
    }
    type Person struct {
        name string
        Date
    }
/*
    type Animal struct {
        name string
        Date
    }
*/
    var per Person = Person{"zs", Date{2012, 12, 12}}
    fmt.Println(per) // {zs {2012 12 12}}
    var per2 Person = Person{"lyw",Date{2018,9,28}}
    fmt.Println(per2)

嵌套定义结构体方式

  • 第一种方式
type 结构体名称1 struct{

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

第一种方式: 没有重名属性的情况

type Person struct {
        name string
        age int
    }
    type Student struct {
        Person
        score float32
    }

    stu := Student{Person{"zs", 18}, 99.5}
    fmt.Println(stu)
    // 结构体嵌套定义时, 如何操作结构体的属性
    //第一种访问方式
    //fmt.Println(stu.Person.name)
    //fmt.Println(stu.Person.age)
    //fmt.Println(stu.score)

    // 第二种访问的方式
    // 会先去Student结构体中查询有没有name属性, 如果有就直接访问
    // 如果没有会继续查找嵌套的匿名结构体中有没有, 如果有就访问匿名结构体中的name属性
    fmt.Println(stu.name)
    fmt.Println(stu.age)
    fmt.Println(stu.score)

第一种方式: 有重名属性的情况

type Person struct {
        name string
        age int
    }
    type Teacher struct {
        Person
        name string
        title string
    }

    tea := Teacher{Person{"luo", 18}, "zs", "老师"}
    fmt.Println(tea)    //{{luo 18} zs 老师}
    fmt.Println(tea.name) // zs 有同名属性会采取就近原则,不会向上查找
    fmt.Println(tea.Person.name) // luo
  • 第二种方式
type 结构体名称1 struct{

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

第二种方式: 没有重名属性的情况

type Object struct {
        name string
    }
    type Person struct {
        Object
        age int
    }
    type Student struct {
        Person
        score float32
    }

    stu := Student{Person{Object{"zs"}, 18}, 99.5}
    fmt.Println(stu) // {{{zs} 18} 99.5}
    fmt.Println(stu.score)//99.5
    fmt.Println(stu.Person.age)//18
    fmt.Println(stu.age) //18
    fmt.Println(stu.Person.Object.name) //zs
    fmt.Println(stu.Person.name)        //zs
    fmt.Println(stu.name)               //zs  会往上查找

第二种方式: 有重名属性的情况

type Object struct {
        name string
    }
    type Person struct {
        Object
        name string
        age int
    }
    type Student struct {
        Person
        name string
        score float32
    }
    stu2 := Student{Person{Object{"lyw"},"zjw",8},"dog",0.1}
    fmt.Println(stu2)   //{{{lyw} zjw 8} dog 0.1}
    fmt.Println(stu2.name) // dog
    fmt.Println(stu2.Person.name) // zjw
    fmt.Println(stu2.Person.Object.name) // lyw
  • 第三种方式
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 float32
    }
    stu := Student{Object{"luo"}, Person{18}, 99.5}
    fmt.Println(stu)       //{{luo} {18} 99.5}
    fmt.Println(stu.Object.name)   //luo
    fmt.Println(stu.name)          //luo
    fmt.Println(stu.Person.age)    //18
    fmt.Println(stu.age)           //18

第三种方式: 有重名属性的情况

type Object struct {
        name string
    }
    type Person struct {
        name string
    }
    type Student struct {
        Object
        Person
        name string
        score float32
    }
    
    stu := Student{Object{"zs"}, Person{"ls"}, "luo",99.5}
    fmt.Println(stu.name)  //luo
    fmt.Println(stu.Object.name)  //zs
    fmt.Println(stu.Person.name)  //ls

结构体的嵌套定义的注意点:

  • 只有匿名结构体才支持向上查找
type Person struct {
        name string
    }
    type Student struct {
        //Person // 匿名属性
        per Person // 命名属性
        age int
    }

    stu := Student{Person{"lnj"}, 18}
    //fmt.Println(stu.per.name)
    fmt.Println(stu.name)    //非匿名属性不会向上查找,会报错
  • 结构体的属性类型不能是当前结构体的类型,如果匿名属性是一个结构体类型, 那么这个结构体类型不能是自己
type Person struct {
      Person // 错误
      name string
  }
  type Student struct {
      *Student  // 正确, 链表
      age int
  }

以上所述就是小编给大家介绍的《13-GoLang结构体》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Amazon Web Services

Programming Amazon Web Services

James Murty / O'Reilly Media / 2008-3-25 / USD 49.99

Building on the success of its storefront and fulfillment services, Amazon now allows businesses to "rent" computing power, data storage and bandwidth on its vast network platform. This book demonstra......一起来看看 《Programming Amazon Web Services》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码