【Go】Go语言结构体笔记

整体介绍

虽然 Go 语言不是传统意义上的面向对象语言,但它提供了结构体(struct)来组织数据,并且可以为结构体绑定方法,从而达到面向对象的部分效果。
关键知识点包括:

  • 结构体定义与实例化

    • 定义结构体时使用 type ... struct{} 语法,字段可以是各种数据类型。
    • 实例化结构体可以使用字面量、new 函数或匿名结构体语法。
  • 方法绑定

    • 为结构体绑定方法时可以选择值接收者或指针接收者。
    • 值接收者方法操作的是副本,指针接收者方法可以修改原始数据。
  • 匿名结构体

    • 无需单独定义类型,定义时直接实例化。
    • 匿名字段:结构体中直接嵌入字段(类型名作为字段名),简化代码。
  • 空结构体

    • 空结构体 struct{} 占用 0 内存,可用于实现方法接收者、作为集合的值(类似只有 key 的字典)或作为信号通道的数据类型。

接下来按照这些知识点整理代码示例。


1. 结构体的定义与实例化

1.1 定义结构体和使用字面量实例化(指针类型和非指针类型)

代码示例:

// 文件名: 01_struct_definition.go
package mainimport "fmt"// 定义一个结构体 Student
type Student struct {id     intname   stringage    intschool string
}func main() {// 使用字面量实例化结构体,并取指针(指针类型实例)pan := &Student{id:     1,name:   "luobozi",age:    18,school: "znlsw",}// 使用指针访问字段(语法糖支持直接 . 操作)fmt.Println("pan.name:", pan.name)// 修改字段pan.age = 20fmt.Printf("pan: %+v\n", pan)// 直接实例化结构体(值类型实例)bo := Student{id:   3,name: "luobozi",age:  18,}fmt.Printf("bo: %+v\n", bo)
}

说明:

  • 使用 &Student{...} 得到结构体指针;直接写 Student{...} 得到值类型实例。
  • 使用字面量可以直接初始化各个字段。

1.2 使用 new 函数实例化结构体

代码示例:

// 文件名: 01_struct_new.go
package mainimport "fmt"type Student struct {id   intname stringage  int
}func main() {// 使用 new 函数实例化,返回的是指针类型luo := new(Student)luo.id = 2luo.name = "luobozi"fmt.Printf("luo: %+v\n", luo)
}

说明:

  • new(Student) 分配内存并返回指针,适用于结构体实例化;与字面量方式相比,new 返回的所有字段都是零值。

2. 值类型与指针类型的赋值

代码示例:

// 文件名: 01_struct_assignment.go
package mainimport "fmt"type Student struct {id   intname stringage  int
}func main() {// 指针类型赋值:两个指针引用同一对象,修改其中一个会影响另一方luo := new(Student)luo.id = 2luo.name = "luobozi"luo2 := luoluo.id = 999fmt.Println("luo2.id:", luo2.id, "luo.id:", luo.id)// 值类型赋值:会拷贝一份数据,互不影响bo := Student{id:   3,name: "luobozi",age:  18,}bo2 := bobo2.name = "张三"fmt.Println("bo2.name:", bo2.name, "bo.name:", bo.name)
}

说明:

  • 指针赋值只是复制地址,值类型赋值会拷贝整个结构体数据。

3. 方法绑定(值接收者与指针接收者)

代码示例:

// 文件名: 01_struct_method.go
package mainimport "fmt"type Student struct {id   intname stringage  int
}// 值接收者方法:对副本操作,修改不会反映到原变量
func (s Student) ChangeName(name string) {fmt.Println("调用方法 ChangeName (值接收者)")s.name = name
}// 指针接收者方法:修改原结构体数据
func (s *Student) ChangeName2(name string) {fmt.Println("调用方法 ChangeName2 (指针接收者)")s.name = name
}func main() {bo := Student{id:   3,name: "luobozi",age:  18,}luo := new(Student)luo.id = 2luo.name = "luobozi"// 调用值接收者方法(修改不会影响原变量)bo.ChangeName("milamn")fmt.Println("bo after ChangeName:", bo)// 调用指针接收者方法(原变量被修改)luo.ChangeName("luji")fmt.Println("luo after ChangeName (值方式调用):", luo)luo.ChangeName2("mikod")fmt.Println("luo after ChangeName2:", luo)
}

说明:

  • 使用值接收者时,方法操作的是结构体副本;而指针接收者方法可以直接修改原数据。

4. 匿名结构体

代码示例:

// 文件名: 01_struct_anonymous.go
package mainimport "fmt"func main() {// 定义并实例化匿名结构体,不需要提前定义类型abc := struct {abcid   intabcaddr string}{abcid:   10,abcaddr: "长沙",}fmt.Println("匿名结构体 abcaddr:", abc.abcaddr)
}

说明:

  • 匿名结构体适用于一次性使用,不需要复用结构体类型的场景。

5. 匿名字段

代码示例:

// 文件名: 01_struct_anonymousField.go
package mainimport "fmt"// 定义结构体时,直接嵌入类型作为匿名字段
type Person struct {stringint
}func main() {// 匿名字段的赋值按照字段顺序进行qwe := Person{"niming", 2,}fmt.Printf("匿名字段 Person: %+v\n", qwe)
}

说明:

  • 匿名字段使得结构体中的字段没有显式的名字,访问时直接用类型名(或通过顺序),可以简化代码结构。

6. 空结构体及其应用

6.1 空结构体作为方法接收者

代码示例:

// 文件名: 01_struct_empty.go
package mainimport "fmt"// 定义空结构体 Temp
type Temp struct{}func (t *Temp) Call() {fmt.Println("call for temp")
}func main() {t := &Temp{}t.Call()
}

说明:

  • 空结构体 struct{} 占用内存为 0,经常用作占位符或实现接口的方法接收者。

6.2 空结构体实现集合(Set)

代码示例:

// 文件名: 01_struct_set.go
package mainimport "fmt"// 定义 Set 类型,其本质上是 map[string]struct{},空结构体不占用内存
type Set map[string]struct{}// 为 Set 添加元素
func (s Set) Append(k string) {s[k] = struct{}{}
}func main() {s := make(Set)s.Append("hello")s.Append("world")// 输出集合中所有的 keyfor key := range s {fmt.Println("set key:", key)}
}

说明:

  • 使用 map[string]struct{} 实现集合(只关心 key,value 为空结构体),这种方式占用内存极小,非常适合存储唯一且不可重复的键。

总结

本篇笔记涵盖了 Go 语言中结构体的核心知识点:

  1. 结构体定义与实例化:包括指针与值的实例化方式以及使用 new 和字面量。
  2. 赋值方式:指针赋值(共享同一内存)与值赋值(拷贝数据)。
  3. 方法绑定:值接收者与指针接收者的区别。
  4. 匿名结构体:直接定义并实例化一次性使用。
  5. 匿名字段:在结构体中嵌入类型作为字段。
  6. 空结构体及集合应用:空结构体用于方法接收者、占位或实现集合。

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

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

相关文章

Three.js 快速入门教程【十八】射线拾取模型——鼠标点击屏幕选中模型或物体

系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…

Object.defineProperty()Proxy详解(Vue23数据劫持实现)

底层原理👇🏿 总结一下,结构应该包括: 1. 方法的基本作用和参数。 2. 数据描述符和存取描述符的区别。 3. 属性定义的内部处理流程。 4. 在Vue中的应用实例。 5. 常见错误和正确实践。 每个部分都要结合搜索结果的信息&…

MySQL 进阶语法:函数、约束、多表查询、事务

目录 一、MySQL 常用函数 1. 字符串函数 1.1 基本字符串操作 1.2 字符串截取与处理 1.3 字符串搜索与替换 2. 数值函数 2.1 基本数学运算 2.2 数学计算 2.3 随机数与符号 3. 日期时间函数 3.1 获取当前时间 3.2 日期时间计算 3.3 日期时间提取 3.4 日期时间格式化…

第 12 章(番外)| Solidity 安全前沿趋势 × 审计生态 × 职业路径规划

🌐 第 12 章(番外)| Solidity 安全前沿趋势 审计生态 职业路径规划 ——做得了审计,也接得了项目,走进 Web3 安全工程师的职业实战地图 ✅ 本章导读 Solidity 安全,不只是代码安全、业务安全、审计安全…

1、pytest基本用法

目录 先给大家分享下学习资源 1. 安装pytest 2. 编写用例规则 3. 执行用例 最近在学习pytest的用法 并且用这套框架替换了原来的unittest, 同是测试框架 确实感觉到pytest更加便捷 这边分享给大家我得学习心得 先给大家分享下学习资源 1 官方文档 pytest 官方…

【sylar-webserver】5 协程调度模块

文章目录 设计思路三种协程的切换 协程调度模块,需要把前面的线程模块和协程模块结合使用 ~ 设计思路 构造函数定义 线程池 基本信息。start(),创建线程池,每个线程创建都执行 run()。每个线程在 run() 里,查找任务队列 m_tasks…

Go 语言规范学习(1)

文章目录 IntroductionNotation示例(Go 语言的 if 语句): Source code representationCharacters例子:变量名可以是中文 Letters and digits Lexical elementsCommentsTokensSemicolons例子:查看程序所有的token Ident…

探索抓包利器ProxyPin,实现手机APP请求抓包,支持https请求

以下是ProxyPin的简单介绍: - ProxyPin是一个开源免费HTTP(S)流量捕获神器,支持 Windows、Mac、Android、IOS、Linux 全平台系统- 可以使用它来拦截、检查并重写HTTP(S)流量,支持捕获各种应用的网络请求。ProxyPin基于Flutter开发&#xff0…

深度学习3-pytorch学习

深度学习3-pytorch学习 Tensor 定义与 PyTorch 操作 1. Tensor 定义: Tensor 是 PyTorch 中的数据结构,类似于 NumPy 数组。可以通过不同方式创建 tensor 对象: import torch# 定义一个 1D Tensor x1 torch.Tensor([3, 4])# 定义一个 Fl…

深入浅出Spring-Boot-3.x.pdf

通过网盘分享的文件:深入浅出Spring-Boot-3.x.pdf 链接: https://pan.baidu.com/s/10ZkhmeIXphEwND9Rv4EBlg?pwduatm 提取码: uatm

springboot启动事件CommandLineRunner使用

什么是CommandRunner CommandRunner是springboot启动完成时会调用的一个runner 启动参数会传递到这个runner 我们能用来做一些初始化工作和缓存预热等工作 ApplicationRunner VS CommandRunner? 这两个Runner作用一样 只是得到的启动参数格式不一样 前者是一个Argument对象…

数据可视化TensorboardX和tensorBoard安装及使用

tensorBoard 和TensorboardX 安装及使用指南 tensorBoard 和 TensorBoardX 是用于可视化机器学习实验和模型训练过程的工具。TensorBoard 是 TensorFlow 官方提供的可视化工具,而 TensorBoardX 是其社区驱动的替代品,支持 PyTorch 等其他框架。以下是它…

蓝桥杯C++基础算法-多重背包

这段代码实现了一个多重背包问题的动态规划解法。多重背包问题与完全背包问题类似,但每个物品有其数量限制。以下是代码的详细思路解析: 1. 问题背景 给定 n 个物品,每个物品有其体积 v[i]、价值 w[i] 和数量 s[i],以及一个容量为…

【SUNO】【AI作词】【提示词】

仿写歌词提示词模板(升级版) 一、仿写目标 风格定位 音乐风格: [填写目标风格,如:民谣/流行/古风/电子/爵士等]参考案例:如《成都》的叙事民谣,《孤勇者》的励志流行。 情感基调: […

26考研——树与二叉树_树与二叉树的应用(5)

408答疑 文章目录 三、树与二叉树的应用哈夫曼树和哈夫曼编码哈夫曼树的定义概念带权路径长度(WPL)计算示例分析 哈夫曼树的构造算法描述哈夫曼树的性质示例 哈夫曼编码Huffman树的编码规则Huffman树的构建过程前缀编码前缀编码的分析及应用 Huffman树的…

【VUE】day06 动态组件 插槽 自定义指令 ESlint

【VUE】day06 动态组件 & 插槽 & 自定义指令 1. 动态组件1.1 通过不同的按钮展示不同的组件1.1.1回顾click 1.2 keep-alive的使用1.3 keep-alive对应的生命周期函数1.3.1 keep-alive的include属性1.3.2 exclude 1.4 组件注册名称和组件声明时name的区别1.4.1 组件声明时…

nodejs-原型污染链

还是老规矩,边写边学,先分享两篇文章 深入理解 JavaScript Prototype 污染攻击 | 离别歌 《JavaScript百炼成仙》 全书知识点整理-CSDN博客 Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客 334-js审计 var express require(expr…

Oracle 数据库通过exp/imp工具迁移指定数据表

项目需求:从prod数据库迁移和复制2个表(BANK_STATE,HBS)的数据到uat数据库环境。 数据库版本:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 迁移工具:客户端exp/imp工具 -- 执行命令 从Prod数据库导出数据exp us…

企业级基于SpringBoot的MQTT的构建和使用

基于SpringBoot的MQTT配置及使用 首先要使用EMQX搭建一个MQTT服务器&#xff0c;参考文档&#xff1a;EMQX快速开始 本着开源分享的观点&#xff0c;闲话不多说&#xff0c;直接上代码 导入Maven <dependency><groupId>org.springframework.integration</gro…

26考研——图_图的代码实操(6)

408答疑 文章目录 五、图的代码实操图的存储邻接矩阵结构定义初始化插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点显示图 邻接表结构定义初始化图插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点…