旺仔小糖

golang struct 2 years ago

go
4929个字符
共有82人围观

struct

Go 语言 为我们提供了几种基本的内置 数据类型,同时,我们可以通过对着几种内置的数据类型的任意组合组装出新的数据类型,这就是 Golang 中的结构体类型。

Golang 中结构体类型的 关键字 是 struct

struct组成

结构体成员是由一系列的成员 变量 构成的,这些成员变量也被称为 “字段”。字段具有以下特性:

  1. 字段拥有自己的类型和值。
  2. 字段名必须唯一。
  3. 字段的类型可以是任意的内置数据类型,也可以是结构体类型。

定义

Go 语言 中 结构体 的定义使用 type 关键字类型名加 struct 关键字的形式。结构体中的每一个成员被称为字段,结构体中每一个字段的 类型 可以是 Golang 中的任意类型也可以是结构体类型。

//定义了一个名为 StructName 的结构体,结构体有三个字段。
type StructName struct {
    Field1 FieldType1 [Tag1]
    Field2 FieldType2 [Tag2]
    Field3 FieldType3 [Tag3]
    ...
}

说明:

定义了一个名为 StructName 的结构体,结构体有三个字段,结构体的字段分别为 Field1、Field2 和 Field3,他们的类型分别为 FieldType1、FieldType2 和 FieldType3。

结构体每个字段后面,都可以有一个可选的 Tag,该 Tag 可以用于说明该字段的意义,比如可以通过 Tag 指定结构体序列化为 Json 时,所使用的字段名。

3种方式实例化struct

Go 语言 中 结构体 定义完之后,并不能直接使用,因此此时还没有分配内存,因此,我们必须在定义完结构体,并实例话之后才可以使用结构体。

Golang 中结构体的实例化主要有三种方式,分别为:使用 变量 定义的方式、使用 new 分配内存和使用 & 符号定义结构体。

1, 变量定义方式

使用 var 关键字定义一个名为 StructName 的结构体变量 varName,后续我们就可以直接使用该变量

//语法
var varName StructName

例子:

//定义一个 Person 结构体,并给结构体赋值
package main

import (
    "fmt"
)

func main() {
    //定义一个 Person 结构体,并给结构体赋值
    type Person struct {
        Name string
        Age  int
    }
    var p Person
    p.Name = "scott"
    p.Age = 18
    fmt.Println("Pserson =", p)
}

2, new分配内存方式

使用 new 关键字为变量 varName 分配内存。

//语法
var varName = new(StructName)

例子:

package main

import (
  "fmt"
)

func main() {
  //使用new分配内存的方式,实例化一个名为 Student 的结构体
  type Student struct {
    Name string
    Age int
    Score float64
  }
  var stu = new(Student)
  stu.Name = "SCOTT"
  stu.Age = 1998
  stu.Score = 100.0
  fmt.Println("Student =", stu)
}

3, &符号定义结构体

使用 & 定义一个名为 varName 的结构体,使用 & 符号定义时,结构体名后面必须要加 {}

//语法
var varName = &StructName{}

例子:

package main

import (
  "fmt"
)

func main() {
  //使用 & 符实例化结构体 Student
  type Student struct {
    Name  string
    Age   int
    Score float64
  }
  var stu = &Student{}
  stu.Name = "SCOTT"
  stu.Age = 1998
  stu.Score = 100.0
  fmt.Println("Student =", stu)
}

struct使用实例

1, 普通struct

//定义一个 Person 结构体,并给结构体赋值
package main

import (
  "fmt"
)

func main() {
  //定义一个 Person 结构体,并给结构体赋值
  type Person struct {
    Name string
    Age  int
  }
  var p Person
  p.Name = "scott"
  p.Age = 18
  fmt.Println("Pserson =", p)
}

解析:我们定义了一个结构体 Person,该结构体有两个字段,一个是 string 类型的 Name,一个是 int 类型的 Age。 接着我们定义了一个 Person 结构体类型的变量 p,并给结构体变量 p 的两个字段赋值,最后使用 print 打印结构体变量。

运行

2, struct嵌套struct

结构体的类型名还可以是一个结构体类型
:::tip 注意 内部结构体字段会直接暴露给外面的结构体 比如下面的例子:Student.Name其实访问的就是Person.Name :::
package main

import (
  "fmt"
)

func main() {
  type Person struct {
    Name string
    Age int
  }
  // 结构体的类型名还可以是一个结构体类型
  type Student struct {
    P Person
    Score float64
  }
  var stu Student
  stu.P.Name = "scott"
  stu.P.Age = 1998
  stu.Score = 100.0
  fmt.Println("Student =", stu)
}

3, 内嵌的struct是可以简写的

package main

import (
  "fmt"
)

func main() {
  type Person struct {
    Name string
    Age  int
  }
  // 结构体的类型名还可以是一个结构体类型
  type Student struct {
    Person 
    Score float64
  }
  var stu Student
  stu.Name = "scott"
  stu.Age = 1998
  stu.Score = 100.0
  fmt.Println("Student =", stu)
}

运行:

下面的写法和上面的等效:

package main

import (
  "fmt"
)

func main() {
  type Person struct {
    Name string
    Age  int
  }
  // 结构体的类型名还可以是一个结构体类型
  type Student struct {
    Person
    Score float64
  }
  var stu Student
  stu.Person.Name = "scott"
  stu.Person.Age = 1998
  stu.Score = 100.0
  fmt.Println("Student =", stu)
}

4,另一种初始化方式

package main

import (
  "fmt"
)

func main() {
  type Person struct {
    Name string
    Age  int
  }
  // 结构体的类型名还可以是一个结构体类型
  type Student struct {
    Person
    Score float64
  }

  stu := Student{
    Person: Person{
      Name: "scott",
      Age:  1998,
    },
    Score: 100.0,
  }

  fmt.Println("stu.Name:", stu.Name)
  fmt.Println("stu.Age:", stu.Age)
  fmt.Println("stu.Score:", stu.Score)
  fmt.Println("Student =", stu)
}

运行:

5,当字段名重复时,会根据表达式优先赋值

比如Person.Name=1,首先去Person里面找看有没有有Name字段,如果有直接赋值;如果没有会去其他结构体成员找Name字段,找到后就赋值

package main

import (
  "fmt"
)

func main() {
  type Person struct {
    Name string
    Age  int
  }
  // 结构体的类型名还可以是一个结构体类型
  type Student struct {
    Person
    Name  string
    Score float64
  }
  stu := Student{
    Person: Person{
      Name: "scott",
      Age:  1998,
    },
    Score: 100.0,
    Name:  "test",
  }

  fmt.Println("stu.Name", stu.Name)

  stu.Name = "赵娘子"
  fmt.Println("stu.Name", stu.Name)
  fmt.Println("stu.Person.Name", stu.Person.Name)

  stu.Person.Name = "宋娘子"
  fmt.Println("stu.Name", stu.Name)
  fmt.Println("stu.Person.Name", stu.Person.Name)
}

运行:

总结

我们可以通过对着几种内置的数据类型的任意组合组装出新的数据类型,这就是 Golang 中的结构体类型。Golang 中结构体类型的关键字是 struct。

tip 补充:

结构体是对现实世界的描述,接口是对某一类行为的规范和抽象;通过它们我们可以实现代码的抽象和复用,同时可以面向接口编程,把具体细节隐藏起来,让写出的代码更灵活,适应能力也更强!