Go笔记(八):结构体

1、类型定义与类型别名

1.1、类型定义

  语法:

type NewType Type

  NewType:表示自定义类型

  Type:表示现有类型
 1 package main
 2 
 3 import "fmt"
 4 
 5 // 类型定义
 6 func definestruct() {
 7    type SnailsInt int
 8    // si为 SnailsInt 类型
 9    var si SnailsInt = 10
10    fmt.Printf("si: %T, %v\n", si, si)
11 }
12 
13 func main() {
14    definestruct()
15 }

  执行结果如下:

 

1.2、类型别名

  语法:

type NewType = Type

  NewType:表示自定义类型

  Type:表示现有类型

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 类型别名
 6 func typealias() {
 7    type SnailsString = string
 8    // str为 string类型
 9    var str SnailsString = "hello world!"
10    fmt.Printf("str: %T, %v\n", str, str)
11 }
12 
13 func main() {
14    typealias()
15 }

1.3、类型定义与类型别名的区别

  1、类型定义是定义一个全新的类型;类型别名是使用一个别名替换之前的类型,没有定义新的类型;

  2、类型别名只在源码中存在,编译后的文件中不存在此别名;

  3、类型别名可以调用原来类型的方法;类型定义无法调用原来类型的任何方法。

2、结构体

  结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

  Go语言中数组可存储同一类型的数据,结构体中可以为不同项定义不同的数据类型。Go语言没有面向对象的概念,可以使用结构体来实现面对对象的特性(继承、组合)。

3、结构体的声明

  结构体定义需要使用 type 和 struct 关键字。struct 定义一个新的数据类型,结构体中有一个或多个成员;type 设定了结构体的名称。

1 type struct_variable_type struct {
2    member definition
3    member definition
4    ...
5    member definition
6 }

  type:结构体定义关键字;

  struct_variable_type:结构体类型名称

  struct:结构体定义关键字

  member definition:成员定义

1、只声明未做初始化的结构体,成员变量用默认值

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 定义结构体
 6 type StudentStruct struct {
 7    name string
 8    stuid string
 9    age int
10 }
11 
12 // 只声明未做初始化的结构体,成员变量用默认值
13 func studentStructDemo() {
14    var ss StudentStruct
15    fmt.Printf(" ss : %v\n", ss)
16 }
17 
18 func main() {
19    studentStructDemo()
20 }

  执行结果如下:

2、结构体,相同数据类型可定义在同一行

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 定义结构体,相同数据类型可定义在同一行
 6 type StructTeacher struct {
 7    tid, name string
 8     age int
 9 }
10 // 只声明未做初始化的结构体,成员变量用默认值
11 func structTeacherDemo() {
12    var st StructTeacher
13    fmt.Printf("st: %v\n", st)
14 }
15 
16 func main() {
17    structTeacherDemo()
18 }

  执行结果如下:

4、结构体的初始化

1、语法

  一旦定义了结构体类型,就可用于变量的声明,格式如下:

variable_name := structure_variable_type {value1, value2...valuen}

  或

variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}

2、示例代码

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 定义结构体
 6 type StudentStruct struct {
 7    name string
 8    stuid string
 9    age int
10 }
11 
12 // 初始化结构体
13 func initStruct() {
14    // 方式一:值列表初始化
15    stu := StudentStruct{"timi", "202208071430", 12}
16    fmt.Printf("stu: %v\n", stu)
17    // 方式二:键值对初始化
18    var stu01 = StudentStruct{name: "zs", stuid: "202304182156", age: 13}
19    fmt.Printf("stu01: %v\n", stu01)
20 }
21 
22 func main() {
23    initStruct()
24 }

  执行结果如下:

  初始化部分结构体变量:

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 初始化部分变量,未初始化的变量为默认值
 6 func initPartStruct() {
 7    // 初始化变量
 8    var stu = StudentStruct{name: "zs", age: 13}
 9    fmt.Printf("stu: %v\n", stu)
10 }
11 
12 func main() {
13    initPartStruct()
14 }

  执行结果如下:

5、匿名结构体

  匿名结构体无需定义结构体名,直接使用,定义在方法内部。  

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 匿名结构体
 6 func secretStruct() {
 7    var cat struct {
 8       name string
 9       age int
10    }
11    cat.name = "kite"
12    cat.age = 1
13    fmt.Printf("cat: %T\n %v\n", cat, cat)
14 }
15 
16 func main() {
17    secretStruct()
18 }
  执行结果如下:

6、结构体指针

1、语法

  结构体指针:指向结构体的指针。

var struct_pointer *struct_type

  struct_pointer : 结构体指针名称

  struct_type : 自定义结构体类型

2、示例代码

 1 package main
 2 
 3 import "fmt"
 4 
 5 type StructPerson struct {
 6    name string
 7    age int
 8 }
 9 // 结构体指针
10 func pointerstructStruct() {
11    var per *StructPerson
12    timi := StructPerson{"zs", 30}
13    per = &timi
14    // 取结构体指针的地址
15    fmt.Printf("per: %p\n", per)
16    fmt.Printf("timi: %p\n", &timi)
17    fmt.Printf("per: %v\n", &per)
18    // 取结构体指针的元素值
19    fmt.Printf("per: %v\n", *per)
20 }
21 
22 func main() {
23    pointerstructStruct()
24 }

  执行结果如下:

  使用new的方式创建结构体指针,示例代码如下:

 1 package main
 2 
 3 import "fmt"
 4 
 5 type StructPerson struct {
 6    name string
 7    age int
 8 }
 9 
10 // 结构体指针,通过  结构体名.成员变量名  访问结构体
11 func visitStruct() {
12    per := new(StructPerson)
13    fmt.Printf("per: %v\n", per)
14    per.name = "timi"
15    per.age = 12
16    fmt.Printf("per: %v\n", per)
17    fmt.Printf("per: %v\n", &per)
18    fmt.Printf("per: %v\n", *per)
19 }
20 
21 func main() {
22    visitStruct()
23 }

  执行结果如下:

7、结构体作为函数参数

  结构体可以作为函数的参数,传递给函数

1、传递结构体

  结构体作为参数传递,传递的是一个结构体副本,函数内部不会改变外部结构体内容。

 1 package main
 2 
 3 import "fmt"
 4 
 5 type StructPerson struct {
 6    name string
 7    age int
 8 }
 9 
10 // 结构体作为函数参数
11 func changeStruct(per StructPerson) {
12    per.name = "ls"
13    per.age = 32
14 }
15 
16 func paramStruct() {
17    per01 := StructPerson{"zs", 45}
18    fmt.Printf("per01: %v\n", per01)
19    // 结构体作为参数传值,值传递,传递的是一个结构体副本,外部传递的结构体内容不会改变
20    changeStruct(per01)
21    fmt.Printf("per01: %v\n", per01)
22 }
23 
24 func main() {
25    paramStruct()
26 }

  执行结果如下:

2、传递结构体指针

  结构体指针作为参数传递,函数内部会改变外部结构体内容。

 1 package main
 2 
 3 import "fmt"
 4 
 5 type StructPerson struct {
 6    name string
 7    age int
 8 }
 9 
10 // 结构体指针作为函数参数
11 func changeStructPoint(per *StructPerson) {
12    per.age = 32
13 }
14 
15 func paramStructPointer() {
16    per01 := StructPerson{"zs", 45}
17    fmt.Printf("per01: %v\n", per01)
18    // 结构体指针作为参数传值,传递的是一个结构体指针,函数内部修改影响外部结构体的内容
19    changeStructPoint(&per01)
20    fmt.Printf("per01: %v\n", per01)
21 }
22 
23 func main() {
24    paramStructPointer()
25 }

  执行结果如下:

8、结构体的嵌套

  Go语言中无面对对象的思想,同时也无继承关系,但可通过结构体嵌套实现这些特性。

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 嵌套结构体
 6 func nestStruct() {
 7    type Book struct {
 8       bname string
 9       pagenum int
10    }
11    bk := Book{"平凡的世界", 257}
12 
13    type Person struct {
14       pname string
15       age int
16       // 嵌套结构体(组合)
17       book Book
18    }
19    per := Person{
20       pname: "zs",
21       age: 12,
22       book: bk,
23    }
24    fmt.Printf("per: %v\n", per)
25    fmt.Printf("per.book.bname: %v\n", per.book.bname)
26    fmt.Printf("per.book.pagenum: %v\n", per.book.pagenum)
27 }
28 
29 func main() {
30    nestStruct()
31 }

  执行结果如下:

  可通过结构体嵌套实现面对对象的继承特性。

 

 1 package main
 2 
 3 import "fmt"
 4 
 5 // 定义动物结构体
 6 type Animal struct {
 7    name string
 8    age int
 9 }
10 func (a Animal) eat() {
11    fmt.Println(a.name + " start eat... ")
12 }
13 // 定义狮子结构体,嵌套动物结构体 等价于  Lion继承自Animal
14 type Lion struct {
15    Animal
16 }
17 // 定义大象结构体,嵌套动物结构体 等价于  Lion继承自Animal
18 type Elephant struct {
19    Animal
20 }
21 
22 func main() {
23    lion := Lion{
24    Animal{
25          name: "美洲狮",
26          age: 12,
27       },
28    }
29    elephant := Elephant{
30       Animal{
31          name: "非洲象",
32          age: 6,
33       },
34    }
35    lion.eat()
36    elephant.eat()
37 }

 

9、结构体集合

  Go中的数组存放相同类型的数据,结构体作为Go中一种复杂数据类型也可存储在数组中。详情如下:

 1 package main
 2 
 3 import "fmt"
 4 
 5 type StructPerson struct {
 6    name string
 7    age int
 8 }
 9 
10 // 结构体集合
11 func structCollection() {
12    var per01 []*StructPerson
13    per01 = []*StructPerson{
14        {"zs", 12},
15        {"ls", 15},
16    }
17    for _, v := range per01 {
18        fmt.Printf("v.name: %v\n", v.name)
19        fmt.Printf("v.age: %v\n", v.age)
20    }
21 }
22 
23 func main() {
24    structCollection()
25 }

  执行结果如下:

10、模拟构造函数

  Go语言中没有Java语言中构造器的概念,但可使用函数来模拟构造函数的功能。
 1 package main
 2 
 3 import "fmt"
 4 
 5 type Student struct {
 6    name string
 7    age int
 8 }
 9 func newStudent(name string, age int) (*Student, error) {
10    if name == "" {
11       return nil, fmt.Errorf("name is not blank")
12    }
13    if age < 0 {
14       return nil, fmt.Errorf("age must ge 0")
15    }
16    return &Student{name: name, age: age}, nil
17 }
18 // 模拟构造器
19 func main() {
20    stu, err := newStudent("jack", 12)
21    if stu == nil {
22       fmt.Printf("err: %v\n", err)
23    } else {
24       fmt.Printf("stu: %v\n", *stu)
25    }
26    stu1, err1 := newStudent("peater", -12)
27    if stu1 == nil {
28       fmt.Printf("err: %v\n", err1)
29    } else {
30       fmt.Printf("stu: %v\n", *stu1)
31    }
32 }
 
posted @ 2023-04-19 08:45  无虑的小猪  阅读(15)  评论(0编辑  收藏  举报