深入解析 Go 语言中的结构体:从基础用法到高级技巧的全方位指南

news2024/11/24 16:06:39

结构体(Struct)是 Go 语言中的一种重要数据类型,能够帮助我们将多个数据组合成一个自定义的类型。与其他编程语言的类(Class)类似,结构体允许我们定义字段、方法,并灵活操作数据。本文将从基础到进阶,详细介绍 Go 语言中的结构体及其应用,力求帮助读者全面理解结构体的使用。

文章目录

    • 一、什么是结构体?
      • 1.1 结构体的基本定义
      • 1.2 创建结构体实例
      • 1.3 结构体的零值
    • 二、结构体的使用
      • 2.1 访问和修改结构体字段
      • 2.2 结构体的指针
      • 2.3 结构体的匿名字段
      • 2.4 结构体的比较
    • 三、结构体的高级用法
      • 3.1 结构体嵌套
      • 3.2 结构体方法
        • 通过指针接收者修改结构体
      • 3.3 结构体的 JSON 序列化与反序列化
        • JSON 序列化
        • JSON 反序列化
      • 3.4 结构体标签(Tags)
    • 四、结构体的内存分配与性能优化
      • 4.1 结构体的内存分配
      • 4.2 结构体的大小与内存对齐
    • 五、总结

在这里插入图片描述

一、什么是结构体?

结构体(struct)是 Go 语言中的一种聚合数据类型,它将多个不同类型的数据组合在一起。通过结构体,我们可以把一个具有多个属性的对象抽象成一个整体。在 Go 语言中,结构体的定义类似于面向对象编程中的类(class),但没有继承与多态的概念。

1.1 结构体的基本定义

结构体的定义使用 type 关键字,格式如下:

type 结构体名称 struct {
    字段名1 字段类型1
    字段名2 字段类型2
    // 可以包含多个字段
}

下面是一个简单的结构体定义示例:

type Person struct {
    name string
    age  int
    address string
}

这个 Person 结构体有三个字段:name 表示姓名,age 表示年龄,address 表示地址。

1.2 创建结构体实例

结构体定义好之后,我们可以通过两种方式创建它的实例:

  1. 使用字段初始化
p1 := Person{name: "Alice", age: 30, address: "Beijing"}
fmt.Println(p1)
  1. 使用 new 函数创建结构体指针
p2 := new(Person)
p2.name = "Bob"
p2.age = 25
p2.address = "Shanghai"
fmt.Println(p2)

1.3 结构体的零值

Go 语言中,结构体的零值是所有字段都为其默认零值的结构体。例如,int 类型字段的零值为 0string 类型字段的零值为 ""

var p3 Person
fmt.Println(p3) // 输出: { 0 }

二、结构体的使用

2.1 访问和修改结构体字段

通过点号操作符(.)可以访问结构体的字段,并可以直接对字段赋值:

p1 := Person{name: "Alice", age: 30, address: "Beijing"}
fmt.Println(p1.name)  // 访问字段
p1.age = 31           // 修改字段
fmt.Println(p1.age)

2.2 结构体的指针

与基本数据类型一样,结构体也可以通过指针进行传递。当我们通过结构体指针访问字段时,Go 语言会自动解引用指针,无需手动使用 * 操作符。

p := &Person{name: "Charlie", age: 22}
fmt.Println(p.name)  // 自动解引用,输出: Charlie
p.age = 23           // 通过指针修改字段
fmt.Println(p.age)

2.3 结构体的匿名字段

Go 语言支持结构体中的匿名字段,匿名字段的类型充当字段名。匿名字段通常用于简化结构体的嵌套结构。

type Contact struct {
    string // 匿名字段
    int    // 匿名字段
}

c := Contact{"Shanghai", 12345}
fmt.Println(c.string, c.int)

2.4 结构体的比较

Go 语言中的结构体可以直接使用 == 运算符进行比较,前提是结构体的所有字段都是可比较的类型。两个结构体只有在字段值完全相等时才被视为相等。

p1 := Person{name: "Alice", age: 30, address: "Beijing"}
p2 := Person{name: "Alice", age: 30, address: "Beijing"}

if p1 == p2 {
    fmt.Println("p1 和 p2 相等")
} else {
    fmt.Println("p1 和 p2 不相等")
}

三、结构体的高级用法

3.1 结构体嵌套

Go 语言允许在一个结构体中嵌套另一个结构体。这种嵌套方式可以帮助我们创建复杂的、层次化的数据结构。

type Address struct {
    city  string
    state string
}

type Person struct {
    name    string
    age     int
    address Address
}

p := Person{
    name: "Alice",
    age:  30,
    address: Address{
        city:  "Beijing",
        state: "China",
    },
}
fmt.Println(p)

3.2 结构体方法

结构体不仅可以包含字段,还可以为结构体定义方法。Go 语言允许为任何类型定义方法,包括结构体。方法的定义类似于函数,只不过方法会将接收者(receiver)指定为结构体的实例。

func (p Person) sayHello() {
    fmt.Printf("Hello, my name is %s\n", p.name)
}

p := Person{name: "Alice", age: 30}
p.sayHello()

在上述例子中,sayHello 方法属于 Person 结构体,它会打印出结构体 name 字段的值。

通过指针接收者修改结构体

如果我们想在方法中修改结构体的字段,就需要使用指针接收者:

func (p *Person) updateName(newName string) {
    p.name = newName
}

p := Person{name: "Alice", age: 30}
p.updateName("Bob")
fmt.Println(p.name) // 输出: Bob

3.3 结构体的 JSON 序列化与反序列化

Go 语言中的结构体可以很方便地与 JSON 进行序列化与反序列化。我们可以使用 encoding/json 包中的 MarshalUnmarshal 函数实现这一功能。

JSON 序列化
import "encoding/json"

p := Person{name: "Alice", age: 30, address: "Beijing"}
jsonData, err := json.Marshal(p)
if err != nil {
    fmt.Println(err)
}
fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30,"address":"Beijing"}
JSON 反序列化
jsonStr := `{"name":"Bob","age":25,"address":"Shanghai"}`
var p Person
err := json.Unmarshal([]byte(jsonStr), &p)
if err != nil {
    fmt.Println(err)
}
fmt.Println(p)

通过序列化和反序列化,我们可以轻松地在 Go 语言和 JSON 数据之间进行转换。

3.4 结构体标签(Tags)

结构体标签是一种用于为结构体字段附加元数据的机制,通常用于序列化和数据库操作中。例如,使用标签自定义字段名的 JSON 序列化:

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

p := Person{Name: "Alice", Age: 30}
jsonData, _ := json.Marshal(p)
fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30}

结构体标签提供了灵活的方式,帮助开发者控制字段的序列化行为。

四、结构体的内存分配与性能优化

在 Go 语言中,结构体可以分配在栈上或堆上,具体取决于编译器的优化策略。一般情况下,较小的结构体会被分配在栈上,而较大的结构体则可能被分配在堆上。

4.1 结构体的内存分配

结构体通常会在栈上分配,以提高访问效率。如果我们使用指针来创建结构体实例,结构体会在堆上分配。

p1 := Person{name: "Alice", age: 30} // 栈上分配
p2 := new(Person)                    // 堆上分配

4.2 结构体的大小与内存对齐

Go 语言中的结构体会根据其字段的类型和顺序进行内存对齐,以提高访问速度。为了优化结构体的内存使用,建议将占用空间较大的字段放在结构体的前面。例如:

type OptimizedStruct struct {
    largeField int64
    smallField int8
}

这样可以避免由于内存对齐导致的空间浪费。

五、总结

Go 语言中的结构体是编写高效、简洁代码的基础工具。通过结构体,我们可以将不同类型的数据组合成一个有意义的整体,并为其定义专属的方法。无论是简单的数据聚合还是复杂的数据结构,结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2205546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

遥控器传输信号算法详解!

一、算法概述 无人机遥控器信号传输算法主要基于无线通信技术,通过特定的调制、编码和信号处理技术,将遥控器的操作指令转化为无线电信号,并传输给无人机。无人机接收到信号后,再将其解码为可识别的指令,从而实现对无…

10月造价、注安考试的押题资料,到底有没有用?

​随着考试的临近,各大考试机构也开始推出了各种考前押题资料。面对网络铺卷而来的考前押题资料,考生自己也无从判断资料的质量,那该如何选择靠谱的押密资料呢?今天考试100就带大家来分析一下: 1、正确看待押题资料 首…

标签页(tabs)内容的显示和样式

1. 代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Tabs Example</title> &…

吴恩达深度学习笔记(一)-基础知识

上图三种神经网络&#xff1a;标准、卷积&#xff08;用于图像&#xff09;、循环&#xff08;序列化数据、时序数据&#xff09; 数据类型&#xff1a;结构化&#xff08;表格&#xff09;、非结构化&#xff08;语言、图片、文本&#xff09; 二分类问题&#xff1a; 0、1判…

Qt-窗口对话框QFileDialog的使用(53)

目录 描述 相关函数 使用 描述 文件对话框 ⽂件对话框⽤于应⽤程序中需要打开⼀个外部⽂件或需要将当前内容存储到指定的外部⽂件 相关函数 打开⽂件&#xff08;⼀次只能打开⼀个⽂件&#xff09; QString getOpenFileName 打开多个⽂件&#xff08;⼀次可以打开多个⽂件…

2024下半年软考中级网络工程师,这100题,必做!

第一章节&#xff1a;计算机硬件基础&#xff08;5&#xff09; 1、在机器指令的地址字段中&#xff0c;直接指出操作数本身的寻址方式称为&#xff08; &#xff09;。 A 隐含寻址 B 寄存器寻址 C 立即寻址 D 直接寻址 答案&#xff1a;C 解析: 立即寻址方式通常直接在指…

Copilot Coaching新功能铸就Word更强

Copilot 的意思是副驾驶。 现在&#xff0c;您的副驾驶教练来了&#xff1a;Copilot Coaching Copilot Coaching 是 Word 中的一项新 Copilot 功能&#xff0c;可在您查看内容时为您提供支持&#xff0c;以实现语法和拼写之外的改进 - 帮助您澄清想法&#xff0c;并为您提供有…

Granafa配置基于elasticsearch数据源的折线图

Granafa可以直接配置基于elasticsearch数据源的折线图&#xff0c;用于展示es库中数据的最值、均值、总量等

AI绘画教程 重阳节海报设计

本期 AI 绘画的主题是海报设计&#xff0c;让我们一同探索能设计出哪些不同风格的海报吧。 今天是重阳节&#xff0c;一起用 AI 绘画制作一些画风清新的海报吧。正所谓 “遥知兄弟登高处&#xff0c;遍插茱萸少一人”。让我们一起通过这些设计&#xff0c;在对长辈的思念与祝福…

2022年全国大学生数学建模竞赛E题目-小批量物料生产安排详解+思路+Python代码时序预测模型

E题补完计划开始,接着之前专栏里面的E题内容写完接下来的所有问题。经过第一问得到了最佳物料编码的前六位排名: 是通过聚合指标和熵权法计算得到的,现在我们需要完成第一问的接下来两个目标,分别是建立物料需求的周预测模型和利用历史数据对预测模型进行评价。对于周预测…

Python物联网编程:10个IoT设备通信的脚本

今天我们要聊的是如何使用Python编写脚本来实现10个IoT设备之间的通信。物联网&#xff08;IoT&#xff09;是一个充满无限可能的领域&#xff0c;它将日常设备连接到互联网&#xff0c;使它们能够互相通信、收集数据并做出响应。Python以其简洁易懂的语法和强大的库支持&#…

力扣题/回溯/N 皇后

N 皇后 力扣原题 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解…

代码随想录day32:动态规划part5

完全背包 二维 /* 完全背包&#xff1a;动态规划 */ int unboundedKnapsackDP(int[] wgt, int[] val, int cap) {int n wgt.length;// 初始化 dp 表int[][] dp new int[n 1][cap 1];// 状态转移for (int i 1; i < n; i) {for (int c 1; c < cap; c) {if (wgt[i -…

009——二叉树

目录 二叉树的五种基本形态&#xff1a; 1.二叉树可以是空树 2.只有一个根节点的树 3.斜树&#xff1a;只有左子树或右子树的树 4.左右孩子都有的树 二叉树的性质&#xff1a; 1.假设根节点是第一层&#xff0c;在二叉树的第i层上最多有2^(n-1)个结点 2.深度为k的二叉树…

【JAVA+flowable】工作流 获取流程节点 几种方法总结

flowable中 获取流程中任务节点的方法有好几种 1.这种是常见的一种 获取流程 正在激活 中任务节点 List<HistoricActivityInstance> historicActivityInstanceList historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId).activityTyp…

Java面试宝典-Java集合02

目录 Java面试宝典-Java集合02 21、TreeMap 和 TreeSet 在排序时如何比较元素&#xff1f; 22、ArrayList 和 LinkedList 的区别是什么&#xff1f; 23、ArrayList 和 Vector 的区别&#xff1f; 24、队列和栈是什么&#xff1f;有什么区别&#xff1f; 25、Queue和Deque的区别…

FreeRTOS对事件标志组的总结

事件标志组 事件标志组讲可以用一个例子来理解&#xff0c;“拼车”&#xff0c;一辆车上有32个座位&#xff08;一个事件标志组的长度&#xff09;&#xff0c;前8个座位用来存放车辆信息&#xff0c;车上可以坐24个人。我们可以选择当所有人都坐满再发车&#xff0c;也可以选…

常用类(一)----包装类的使用和分析

文章目录 1.包装类2.课堂测试题3.包装类方法4.Integer创建机制5.Integer面试题 1.包装类 概念&#xff1a;基本数据类型对应的类就是包装类&#xff0c;就是为了把基本数据类型转换为包装类&#xff0c;使用这个类里面的方法操作数据----装箱的过程&#xff1b; //装箱&#…

算子级血缘在数据全链路变更感知、影响分析场景下的应用

我们都知道&#xff0c;数据的完整性、可用性和准确性对企业决策至关重要。数据采集、存储、加工到消费的任何一个环节失误都可能对最终的数据质量产生负面影响。而今&#xff0c;数据量激增、数据资产多样化及数据加工链路复杂化&#xff0c;数据全链路变更感知监控和影响面精…

Magnum IO

NVIDIA Magnum IO 文章目录 前言加速数据中心 IO 性能,随时随地助力 AINVIDIA Magnum IO 优化堆栈1. 存储 IO2. 网络 IO3. 网内计算4. IO 管理跨数据中心应用加速 IO1. 数据分析Magnum IO 库和数据分析工具2. 高性能计算Magnum IO 库和 HPC 应用3. 深度学习Magnum IO 库和深度…