GO语言学习笔记5——结构体

结构体 struct

  • 用来自定义复杂数据结构

  • struct 里面可以包含多个字段(属性)

  • struct类型可以定义方法,注意和函数的区别

  • struct类型是值类型

  • struct类型可以嵌套

  • GO语言没有class类型,只有struct 类型

  • 声明:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    type 标识符 struct{
    field1 type
    field2 type
    }
    //例
    type Student struct{
    Name string
    Age int
    Score int
    }
    var stu Student
    stu.Name = "tony"
    stu.Age = 18
  • 定义的三种方式

    1
    2
    3
    var stu Student
    var stu *Student = new(Student) //指针
    var stu *Student = &Student{} //指针
    • 指针访问元素时,用(*stu).Age 或者 直接 stu.Age 也可以,GO做了优化
  • struct的内存布局,所有字段在内存是连续的

  • golang中struct没有构造函数,一般可以使用工厂模式来解决

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Package model
    type student struct{
    Name string
    Age int
    }
    func NewStudent(name string, age int) *student{
    return &student{
    Name:name,
    Age:age,
    }
    }
    Package main
    S := new(student)
    S := model.NewStudent("dante",18)
  • 再次强调

    • make用来创建map,slice,channel
    • new 用来创建值类型
      • struct是值类型
  • 匿名字段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    type Cart struct {
    name string
    age int
    }
    type Train struct {
    Cart
    int
    }
    func main() {
    var t Train
    t.name = "train"
    t.age = 100
    t.int = 666
    fmt.Println(t)
    }
    • 如果匿名字段是结构体,可以简化结构体多层调用
      • 如果有冲突就不能用简化的了,还得指定具体子结构体
        • t.Cart1.name = “xxx”
        • t.Cart2.name = “222”
    • 如果匿名字段是普通值类型,那么就直接把值类型作为成员调用
      • 但是这都是在没有冲突下使用,如果有冲突,就不能这么用了
  • GO中继承通过匿名字段来完成

struct的tag机制

tag 是放在结构体中元素后面的字符串

我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化。

  • 背景

    • 如果结构体里面的字段首字母是小写,作为另一个包中的json序列化函数就无法访问这些小写的结构体,无法进行序列化
    • 虽然可以通过将结构体中的成员首字母大写来解决,但是在有时候和对方通信,协议中大家约定是小写字母,此时该怎么办呢?
    • 这时候就用到tag
  • 解决方案

    1
    2
    3
    4
    5
    type Student struct {
    Name string `json:"student_name"`
    Age int `json:"age"`
    Score int `json:"score"`
    }
    • 这样json包能通过反射获取到tag内容,并序列化时按tag中的内容进行

结构体的方法

  • GO中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是struct
  • 定义

    • func (recevier type) methodName(参数列表)(返回值列表){}
  • 例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    type integer int
    func (p integer) print() {
    fmt.Println("p is ", p)
    }
    func (p *integer) set(b integer) {
    *p = b
    }
    type Student struct {
    Name string
    Age int
    Score int
    sex int
    }
    func (p *Student) init(name string, age int, score int) {
    p.Name = name
    p.Age = age
    p.Score = score
    fmt.Println(p)
    }
    func (p Student) get() Student {
    return p
    }
    func main() {
    var stu Student
    stu.init("stu", 10, 200)
    stu1 := stu.get()
    fmt.Println(stu1)
    var a integer
    a = 100
    a.print()
    a.set(1000)
    a.print()
    }
  • 使用匿名字段实现继承,同样也能继承方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package main
    import "fmt"
    type Car struct {
    weight int
    name string
    }
    func (p *Car) Run() {
    fmt.Println("running")
    }
    type Bike struct {
    Car
    lunzi int
    }
    type Train struct {
    c Car
    }
    func main() {
    var a Bike
    a.weight = 100
    a.name = "bike"
    a.lunzi = 2
    fmt.Println(a)
    a.Run()
    var b Train
    b.c.weight = 100
    b.c.name = "train"
    b.c.Run()
    }
  • 多重继承也是使用匿名字段实现

    • 如果各子结构体内有字段冲突就不能使用简化指定方法,要具体到子结构体名称去调用。
  • 如果结构体的实现了某些接口的方法,就等于实现了这个接口

    • 就可以获得这个接口的特性
    • 例如:结构体实现一个格式化打印接口的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package main
    import "fmt"
    type Car struct {
    weight int
    name string
    }
    type Train struct {
    Car
    }
    func (p Train) String() string {
    str := fmt.Sprintf("name=[%s] weight=[%d]", p.name, p.weight)
    return str
    }
    func main() {
    var b Train
    b.weight = 100
    b.name = "train"
    fmt.Printf("%s", b)
    }

本文标题:GO语言学习笔记5——结构体

文章作者:Yang Shuai

发布时间:2019年06月10日 - 15:06

最后更新:2019年06月10日 - 15:06

原始链接:https://ysbbswork.github.io/2019/06/10/GO语言学习笔记5——结构体/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!