《Go程序设计语言》学习笔记之结构体
《Go程序设计语言》学习笔记之结构体
一. 环境
Centos8.5, go1.17.5 linux/amd64
二. 概念
结构体是将零个或者多个任意类型的命名变量组合在一起的聚合数据类型。每个变量都叫做结构体的成员。
三. 声明/初始化
1) 定义一个结构体类型 Human,然后通过它定义一个命名结构体变量 child。
8 type Human struct {
9 Name string
10 Age int
11 Height float64
12 }
13
14 var child Human
15
16 func main() {
17 child.Name = "Jim"
18 child.Height = 90.0
19 child.Age = 4
20
21 fmt.Printf("%#v\n", child)
22 }
运行结果如下

结构体的成员变量通常一行写一个,变量的名称在类型的前面,但是相同类型的连续成员变量可以写在同一行上。
成员变量的顺序对于结构体同一性很重要,如果我们调整了成员的顺序,那么我们就在定义一个不同的结构体类型。
如果一个结构体的成员变量名称是首字母大写的,那么这个变量是可导出的,这个是Go最主要的访问控制机制。一个结构体可以同时包含可导出和不可导出的成员变量。
命名结构体类型 S 中,不可以定义一个拥有相同结构体类型 S 的成员变量,也就是一个聚合类型不可以包含它自己。否则,编译会报错,提示“无效的递归类型”,如下

但是,结构体类型 S 中 可以定义一个 S 的指针类型,即 *S ,这样可以创建一些递归数据结构如链表、树。
2) 零值
结构体的零值由结构体成员的零值组成。通常情况下,零值是一个默认的自然的、合理的值。
26 type Test struct {
27 Size int
28 Buffer string
29 IsBool bool
30 Mut sync.Mutex
31 }
32
33 func main() {
34 t1 := Test{}
35 fmt.Printf("%#v\n", t1)
36 }
运行结果如下

结构体类型 Test 前面三个成员的零值,整型的零值为 0,字符串类型的成员零值为空字符串, 布尔类型的成员零值为 false,sync.Mutex类型的成员是一个可以直接使用且未锁定状态的互斥锁。
3) 通过结构体字面量来初始化结构体变量
一种方式是按照正确的顺序,为每个成员变量指定一个值,如 p1。这种方式适用于小型的大家都比较容易理解的结构体,比如 Point 类型结构体。
另一种方式是通过指定部分或全部成员变量的名称和值来初始化结构体变量,如 p2。这种方式一般用的较多。
8 type Point struct {
9 X float64
10 Y float64
11 }
12
13 func main() {
14 p1 := Point{3.0, 4.0}
15 p2 := Point{X: 2.0, Y: 5.0}
16
17 fmt.Printf("%v\n", p1)
18 fmt.Printf("%v\n", p2)
19 }
初始化一个结构体变量的指针
20 pp := &Point{5, 8}
21 fmt.Printf("%v\n", *pp)
这个等价于
23 pp2 := new(Point)
24 *pp2 = Point{5, 8}
25 fmt.Printf("%v\n", *pp2)
&Point{5, 8} 这种方式可以直接使用在一个表达式中,例如函数调用。
四. 访问
结构体的每个成员都可以通过点号方式来访问,也可以获取成员变量的地址,然后通过指针来访问它。
h1 通过点号来访问成员 Age,h1 通过指针修改了成员变量 Height 的值。
19 func main() {
20 h1 := Human{"Jim", 21, 65}
21
22 h1.Age++
23 *(&h1.Height) += 2.0
24 fmt.Printf("%#v\n", h1)
25 }
运行结果如下

五. 比较
如果结构体的所有成员变量都可以比较,那么这个结构体就是可比较的。两个结构体的比较可以使用 == 或者 !=。== 操作符按照顺序比较两个结构体变量的成员变量。
第28和第29两行代码的语句是等价的
26 p1 := Point{1, 2}
27 p2 := Point{2, 1}
28 fmt.Printf("%t\n", p1.X == p2.X && p1.Y == p2.Y)
29 fmt.Printf("%t\n", p1 == p2)
可比较的类型都可以做为 map 的键类型,结构体变量 addr 作为 map 变量 acce 的键值
19 type address struct {
20 Ip string
21 Port string
22 }
23
24 func main() {
25 addr := address{"127.0.0.1", "9090"}
26 acce := make(map[address]int)
27 acce[addr]++
28 fmt.Printf("%v\n", acce)
29 }
运行结果如下

六. 使用
1) 作函数参数
一般使用指针传递的方式,一是出于效率的考虑,二 是当需要结构体变量时这种方式就是必需的。
值传递,调用者接收到的实参的一个副本,并不是实参的引用。
2) 结构体嵌套和匿名成员
a. 结构体嵌套,这个机制可以让我们将一个命名结构体当作另一个结构体类型的匿名成员使用,并提供了方便的访问方式。
借用书上的例子,下面示例代码,结构体中嵌套了命名结构体,访问结构体变量 w 中的成员时,使用到了中间的结构体变量。
8 type Point struct {
9 X int
10 Y int
11 }
12
13 type Circle struct {
14 Center Point
15 Radius int
16 }
17
18 type Wheel struct {
19 Circle Circle
20 Spokes int
21 }
22
23 func main() {
24 var w Wheel
25 w.Circle.Center.X = 2
26 w.Circle.Center.Y = 3
27 w.Circle.Radius = 5
28 w.Spokes = 10
29 fmt.Printf("%#v\n", w)
30 }
在 Go 中,可以定义不带名称的结构体成员,只需要指定类型即可;这种结构体成员称作匿名成员。这个结构体成员必须是一个命名类型或者一个指向命名类型的指针。
8 type Point struct {
9 X int
10 Y int
11 }
12
13 type Circle struct {
14 Point
15 Radius int
16 }
17
18 type Wheel struct {
19 Circle
20 Spokes int
21 }
22
23 func main() {
24 var ww Wheel
25 ww.X = 2
26 ww.Y = 3
27 ww.Radius = 5
28 ww.Spokes = 10
29 fmt.Printf("%#v\n", ww)
30
31 var w Wheel
32 w.Circle.Point.X = 2
33 w.Circle.Point.Y = 3
34 w.Circle.Radius = 5
35 w.Spokes = 10
36 fmt.Printf("%#v\n", w)
37
38 }
Circle 中有一个匿名成员 Point,Wheel 中有一个匿名成员 Circle。结构体变量 ww 可直接访问到需要的成员变量,而不需要指定一大串中间变量。结构体变量 w 的访问成员的方式也是正确,可以看到这种方式相对繁琐了不少。
运行结果如下

b. 嵌套结构体的初始化
与前面一致。一种是按照顺序初始化,另一种是使用成员变量的名称与值进行初始化。
23 func main() {
24 w := Wheel{Circle{Point{3, 4}, 5}, 10}
25 fmt.Printf("%v\n", w)
26
27 ww := Wheel{
28 Circle: Circle{
29 Point: Point{
30 X: 3,
31 Y: 4,
32 },
33 Radius: 5,
34 },
35 Spokes: 10,
36 }
37 fmt.Printf("%v\n", ww)
38 }
两种方式打印结果一致

第31行,33行,35行最后面的逗号都需要带上,不然会编译报错。
c. 匿名成员不一定是结构体类型,任何命名类型或者指向命名类型的指针都可以。
结构体类型 MyType 中的成员 Ages 和 Weight 都是自定义的类型,Name 是内置类型,ContactInfo 是嵌套的结构体类型。
23 type Ages int
24 type Weight float64
25
26 type ContactInfo struct {
27 Addr string
28 PhoneNum string
29 }
30
31 type MyType struct {
32 Name string
33 Ages
34 Weight
35 ContactInfo
36 }
37
38 func main() {
39 var t1 MyType
40 t1.Ages = 20
41 t1.Weight = 55
42 t1.Name = "Bob"
43 t1.Addr = "BeiJing"
44 t1.PhoneNum = "18888888888"
45 fmt.Printf("%v\n", t1)
46 }
打印结果如下

以快捷方式访问匿名成员的内部变量同样适用于访问匿名成员的内部方法。因此,外围的结构体类型获取的不仅仅是匿名成员的内部变量,还有相关的方法。
《Go程序设计语言》学习笔记之结构体的更多相关文章
- c语言学习笔记之结构体存储
今天讲讲结构体存储问题 首先,结构体简单说是对不同类型的封装,一开始我们可能会想结构体在内存中的存储的大小是直接元素的和 例如 我们可能会觉得是 结构体大小=int(4个字节)+ short(2个字节 ...
- C语言学习笔记--枚举&结构体
枚举 枚举是一种用户定义的数据类型,它用关键字enum以如下语法格式来声明: enum 枚举类型名字 {名字0,名字1,...,名字n}: 枚举类型名字通常并不真的使用,要用的是大括号里面的名字,因为 ...
- C语言学习笔记10-结构体、枚举、联合体
C语言学习笔记10-结构体.枚举.联合体 待传
- contiki学习笔记---process结构体
process,字面意义,进程,看看它的结构 struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #def ...
- C#学习笔记之结构体
1.概述 结构是一种与类相似的数据类型,不过它较类更为轻量,一般适用于表示类似Point.Rectangle.Color的对象.基本上结构能办到的类全都能办到,但在某些情况下使用结构更为合适,后面会有 ...
- 《PHP7底层设计与源码实现》学习笔记2——结构体对齐
书里给了一段代码,假如有个结构体如下: struct test { char a; int b; long c; void* d; int e; cha ...
- C程序设计语言学习笔记
在Windows下运行C语言程序 Windows下的编程工具使用 VC 6.0,下面讲解如何在VC 6.0下运行上节的"Hello, world"程序. 1) 新建Win32 Co ...
- 【C#学习笔记】结构体使用
using System; namespace ConsoleApplication { struct _st { public string name; public int age; } clas ...
- Go语言学习笔记十: 结构体
Go语言学习笔记十: 结构体 Go语言的结构体语法和C语言类似.而结构体这个概念就类似高级语言Java中的类. 结构体定义 结构体有两个关键字type和struct,中间夹着一个结构体名称.大括号里面 ...
- 2017-05-4-C语言学习笔记
C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...
随机推荐
- jvm的简介
什么是jvm? java虚拟机就是二进制字节码的运行环境.我们可以把jvm看做是运行在不同系统上的一个软件应用的计算机,就比如说我们要打开图片,就得用看图软件,或者我们要对文件进行解压,是不是得用解压 ...
- Linux 中Yum命令使用方法
Linux系统下常用yum安装命令详解 yum常用安装命令 使用yum安装和卸载软件,有个前提是yum安装的软件包都是rpm格式的. 1.安装killall命令yum install -y psm ...
- 使用JS访问本地数据库
1 前言 有时候,数据业务比较大,比如查询百万级的数据,如果使用JSP查询数据库,JSP的返回结果一般放在域名后面返回给客户端,而返回结果的长度是有限制的,数据过长可能会丢失部分数据:另一方面数据量大 ...
- lsattr命令
lsattr命令 lsattr命令用于显示文件的属性. 语法 lsattr [-RVadlv] [file | folder] 参数 -a: 显示所有文件和目录,包括以.为名称开头字符的额外内建,即现 ...
- std::vector<std::string> 与 char** 的转换
vecotr 容器中插入多条字符串,再将 vector 的地址转换为 char** 代码如下: #include <stdio.h> #include <string> #in ...
- win32 - Session 0 隔离
在Windows XP,Windows Server 2003和Windows操作系统的早期版本中,所有服务都与登录控制台的第一个用户在同一会话中运行.该会话称为会话0.在会话0中一起运行服务和用户应 ...
- 学习go语言编程之面向对象
类型系统 类型系统是指一个语言的类型体系结构,一个典型的类型系统通常包含如下基本内容: 基础类型,如:byte.int.bool.float等 复合类型,如:数组.结构体.指针等 可以指向任意对象的类 ...
- Nacos2作为Dubbo3的配置中心踩坑总结
本文阐述问题所使用的组件版本分别是,Dubbo:3.2.4,Nacos服务端:2.2.3,Nacos客户端:2.2.4. 在Dubbo3的官方文档中,关于如何使用Nacos作为配置中心的详细介绍参考: ...
- AirtestProject浅尝辄止
AirtestProject是什么 AirtestProject是由网易游戏推出的UI自动化测试解决方案,主要包含3部分内容: 1.Airtest框架:跨平台的,基于图像识别的UI自动化测试框架,支持 ...
- django时区相关说明
# naive time 从字面意思上理解,这是个"幼稚的时间",所以可以理解为它是个本地时间,不带时区信息,不能直接用于存储,如下 import datetime datetim ...