你知道 Go 结构体和结构体指针调用有什么区别吗?

server/2024/9/23 11:19:12/

结构体是什么

在 Go 语言中有个基本类型,开发者们称之为结构体(struct)。是 Go 语言中非常常用的,基本定义:

type struct_variable_type struct {member definitionmember definition...member definition
}

简单示例:

package mainimport "fmt"type Vertex struct {Name1 stringName2 string
}func main() {v := Vertex{"脑子进了", "煎鱼"}v.Name2 = "蒸鱼"fmt.Println(v.Name2)
}

输出结果:

蒸鱼

这部分属于基础知识,因此不再过多解释。如果看不懂,建议重学 Go 语言语法基础。

结构体和指针调用

讲解前置概要后,直接进入本文主题。如下例子:

type MyStruct struct {Name string
}func (s MyStruct) SetName1(name string) {s.Name = name
}func (s *MyStruct) SetName2(name string) {s.Name = name
}

该程序声明了一个 User 结构体,其包含两个结构体方法,分别是 SetName1 和 SetName2 方法,两者之间的差异就是引用的方式不同。
进一步延伸,这两者有什么区别,什么情况下用哪种,有没有什么注意事项?
注:很巧,我有一个朋友,当年刚上手 Go 语言时,就纠结过这个问题。

两者区别

从许多小伙伴的反馈来看,这两个例子之间的区别可能会让人感到困惑,经常会有人纠结要不要使用 “指针”,又担心 GC 什么的。
实际上情况没那么复杂,看看下面的例子:

func (s MyStruct) SetName1(name string) 
func (s *MyStruct) SetName2(name string)

当在一个类型上定义一个方法时,接收器(在上面的例子中是 s)的行为就像它是方法的一个参数一样。其相当于:

 func SetName1(s MyStruct, name string){u.Name = name}func SetName2(s *MyStruct,name string){u.Name = name}

因此结构体方法是要将接收器定义成值,还是指针。这本质上与函数参数应该是值还是指针是同一个问题。

如何选择

整体有以下几个考虑因素,按重要程度顺序排列:

  1. 在使用上的考虑:方法是否需要修改接收器?如果需要,接收器必须是一个指针。

  2. 在效率上的考虑:如果接收器很大,比如:一个大的结构体,使用指针接收器会好很多。

  3. 在一致性上的考虑:如果类型的某些方法必须有指针接收器,那么其余的方法也应该有指针接收器,所以无论类型如何使用,方法集都是一致的。

回到上面的例子中,从功能使用角度来看:

  • 如果 SetName2 方法修改了 s 的字段,调用者是可以看到这些字段值变更的,因为其是指针引用,本质上是同一份。
  • 相对 SetName1 方法来讲,该方法是用调用者参数的副本来调用的,本质上是值传递,它所做的任何字段变更对调用者来说是看不见的。

另外对于基本类型、切片和小结构等类型,值接收器是非常廉价的。
因此除非方法的语义需要指针,那么值接收器是最高效和清晰的。在 GC 方面,也不需要过度关注。出现时再解决就好了。

总结

在本文中,我们针对 Go 结构体和结构体指针调用有什么区别,这个问题进行了深入浅出的分析和说明。


http://www.ppmy.cn/server/30015.html

相关文章

【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序

本文设计知识点 树 图论 阶乘 组合 深度优先搜索 图论知识汇总 LeetCoce1916. 统计为蚁群构筑房间的不同顺序 你是一只蚂蚁,负责为蚁群构筑 n 间编号从 0 到 n-1 的新房间。给你一个 下标从 0 开始 且长度为 n 的整数数组 prevRoom 作为扩建计划。其中&#xff0…

借助Aspose.SVG图像控件,在线将 PNG 转换为 XML

Aspose.SVG for .NET 是用于SVG文件处理的灵活库,并且与其规范完全兼容。API可以轻松加载,保存和转换SVG文件,以及通过其文档对象模型(DOM)读取和遍历文件的元素。API独立于任何其他软件,使开发人员无需使用…

预训练语言模型

一.预训练模型的基本介绍 预训练模型是一种在大规模数据上训练而得的模型,通常通过无监督学习或自监督学习的方式进行。在预训练阶段,模型被训练来学习数据的内在表示,而无需标注数据或任务特定的目标函数。这种学习能力使得预训练模型可以捕…

【Cpp】类和对象#构造函数 析构函数

标题:【Cpp】类和对象#构造函数 析构函数 水墨不写bug (图片来源于网络) 正文开始: (一)构造函数 构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但…

Faststone Capture:一触即发的效率革命【AI写作】

首先,这篇文章是基于笔尖AI写作进行文章创作的,喜欢的宝子,也可以去体验下,解放双手,上班直接摸鱼~ 按照惯例,先介绍下这款笔尖AI写作,宝子也可以直接下滑跳过看正文~ 笔尖Ai写作:…

华为Pura70发布,供应链公司进入静默保密期

保密措施:与华为Pura70发布相关的供应链公司在产品发布前后处于静默保密期。这可能是由于华为对于手机供应链的一些信息处于保密状态,尤其是关于麒麟芯片的代工厂商等敏感信息。这种保密措施有助于保持产品的神秘感,调动用户的好奇心&#xf…

基于Springboot的CSGO赛事管理系统

采用技术 基于Springboot的CSGO赛事管理系统的设计与实现~ 开发语言:Java 数据库:MySQL 技术:SpringBootMyBatis 工具:IDEA/Ecilpse、Navicat、Maven 页面展示效果 系统功能 首页 赛事信息 赛事通知 参赛队注册页面 管理…

UDP的报文结构和注意事项

目录 正文: 1.概述 2.UDP的报文结构 3.注意事项 总结: 正文: 1.概述 UDP(User Datagram Protocol)是一种无连接的传输层协议,它提供了一种简单的数据传输服务,不保证数据的可靠传输。在网…