Go笔记(八):结构体
1、类型定义与类型别名
1.1、类型定义
语法:
type NewType Type
NewType:表示自定义类型
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 : 结构体指针名称
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、模拟构造函数
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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)