当前位置: 首页 > news >正文

Go - 10. * 值类型和指针类型的差异

目录

一.引言

二.接收者类型

三.代码示例

1.指针接收者

2.值接收者

3.运行结果对比

4.代码修改

5.刨根问底

四.总结


一.引言

go 语言中 func (c *Title) 和 func (c Title) 两个方法的传参差一个 * 号,二者的区别是一个是指针类型,一个是值类型,下面我们简单整理下二者在 Func 中的差异和使用示例。

二.接收者类型

  • 指针接收者 (*Type):

    • 当方法的接收者是指针类型时,方法可以修改接收者指向的对象的状态。
    • 由于指针接收者可以避免复制整个对象,因此适合用于较大的结构体。
    • 可以通过指针调用方法,或通过值调用方法,Go 会自动将值的地址传递给指针接收者。
  • 值接收者 (Type):

    • 当方法的接收者是值类型时,方法接收者的值是通过值复制传递的,因此方法内部对接收者的任何修改不会影响到原始对象。
    • 适合用于小型结构体或者值不变的方法。
    • 只有值调用方法时才会调用值接收者的方法,不能通过指针调用该方法。

三.代码示例

1.指针接收者

package mainimport "fmt"// 定义结构体
type Title struct {title string
}// 使用指针接收者的方法
func (c *Title) SetTitle(title string) {c.title = title
}// 使用指针接收者的方法
func (c *Title) GetTitle() string {return c.title
}func main() {advisor := Title{}// 调用 SetTitle 方法(通过值调用)-- Go 会自动将地址传递给指针接收者advisor.SetTitle("New Title")// 调用 GetTitle 方法获取设置后的值fmt.Println(advisor.GetTitle())
}

2.值接收者

package mainimport "fmt"// 定义结构体
type Title struct {title string
}// 使用值接收者的方法
func (c Title) SetTitle(title string) {c.title = title
}// 使用值接收者的方法
func (c Title) GetTitle() string {return c.title
}func main() {advisor := Title{}// 调用 SetTitle 方法(通过值调用)advisor.SetTitle("New Title")// 调用 GetTitle 方法fmt.Println(advisor.GetTitle())
}

3.运行结果对比

  • 在第一种情况下(指针接收者),调用 SetTitle 后,GetTitle 会返回 "New Title",因为 SetTitle 方法修改了 title 字段。
  • 在第二种情况下(值接收者),调用 SetTitle 后,GetTitle 仍然会返回空字符串 "",因为 SetTitle 方法修改的是 advisor 的副本,而不是原始对象。

4.代码修改

下面我们对值接收者代码做简单修改,使得我们 GetTitle 方法可以获得结果,由于值类型只能获取原始结构的信息,无法修改信息,所以 SetTitle 这里是不生效的,如果想要获取 title,我们在初始化结构体的时候就定义好 title 的值,这样就可以获取了。

package mainimport "fmt"// 定义结构体
type Title struct {title string
}// 使用值接收者的方法
func (c Title) SetTitle(title string) {c.title = title
}// 使用值接收者的方法
func (c Title) GetTitle() string {return c.title
}func main() {advisor := Title{}advisor.title = "New Title V2"// 调用 SetTitle 方法(通过值调用)advisor.SetTitle("New Title")// 调用 GetTitle 方法fmt.Println(advisor.GetTitle())
}

5.刨根问底

	advisor := Title{}advisor.title = "New Title V2"

Q: 上面我们通过下述方法为 Title 类设置了标题,按照上面的思维,能够修改变量,那这里 advisor 是指针还是值呢? 

A: advisor 不是指针,而是一个 Title 结构体类型的实例。这个实例是值类型的,而不是指针类型的。

值类型

当使用 Title{} 初始化结构体实例时,产生的是一个值类型的变量。这意味着 advisor 变量直接存储结构体实例的数据。

package mainimport "fmt"type Title struct {title string
}func main() {// 初始化结构体实例,advisor 是 Title 类型的值advisor := Title{}// 设置字段值advisor.title = "New Title V2"// 输出fmt.Println(advisor.title) // 输出: New Title V2
}

指针类型

如果需要得到一个指针类型,可以使用 & 操作符,这样 advisor 变量将是一个指向 Title 结构体实例的指针。

func main() {// 初始化结构体实例,并获取其指针advisor := &Title{}// 通过指针来设置字段值advisor.title = "New Title V2"// 输出fmt.Println(advisor.title)  // 输出: New Title V2
}

上面两个方法都会输出 "New Title V2",这里如果单纯构建结构体 Title 的话, Title 和 &TItle 是一样的,它们在初始化结构体实例方面并没有区别。显著的区别在于将实例传递到函数中时的行为。

package mainimport "fmt"type Title struct {title string
}func main() {// 值类型advisorValue := Title{}advisorValue.title = "ddd"fmt.Println("Value Type:", advisorValue.title)// 指针类型advisorPointer := &Title{}advisorPointer.title = "ddd"fmt.Println("Pointer Type:", advisorPointer.title)
}

上面两个方法达到的需求是一样的,那实际场景中我们该写哪种呢?

简单和小型结构体:

如果你的结构体很简单并且字段比较少(如本例中的 Title 结构体),且多数情况下仅做读取操作,使用值类型创建可以更加直观和简单。
推荐使用值类型:advisorValue := Title{}


修改结构体数据:

如果你的代码需要在多个函数中修改结构体字段,使用指针类型可以避免复制整个结构体,有助于提高性能。
推荐使用指针类型:advisorPointer := &Title{}


一致性:

如果整个代码库中大多数情况下都需要频繁对结构体进行修改,使用指针类型可以保持一致性,避免混淆。在这种情况下,可以统一使用指针类型。

我们上面的示例中,如果 title 写死了只做读取,那我们就 := Title,如果我们需要频繁修改 title 值,就是用 := &Title。

四.总结

  • 指针接收者 用于需要修改接收者内部状态的方法,并且适合较大的结构体实例。
  • 值接收者 用于不需要修改内部状态的方法,只适用于小型结构体或方法调用时不涉及修改操作。

选择使用指针接收者还是值接收者取决于您的具体需求和结构体的大小。对于需要修改内部状态、传递较大结构体的情况,推荐使用指针接收者。对于不修改状态的情况,可以使用值接收者。

http://www.lryc.cn/news/418010.html

相关文章:

  • waf绕过:网络安全狗绕过
  • Django中的模型小总结:
  • 深入理解 RDMA 的软硬件交互机制
  • 轻优图片编辑压缩官网 轻优图片编辑压缩
  • 封装el-table 基于element封装可配置JSON表格组件
  • Springboot 开发之 Quartz 任务调度框架简介
  • 详解Xilinx FPGA高速串行收发器GTX/GTP(4)--TX/RX接口的数据位宽和时钟设计
  • idea个人常用快捷键设置
  • 超实用 不再担心猫咪掉毛 一文教你养宠家庭空气净化器怎么选
  • 深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
  • 如何在印尼新闻媒体发布新闻稿件:通稿宣发的好处
  • 如何在 Linux 系统上更改 SSH 服务端口以增强服务器安全性
  • c++11新特性 -nullptr
  • kubernets学习笔记——Kubernets 命令行工具 kubectl
  • Hadoop单机及集群部署
  • 使用es-hadoop同步hive和es之间数据
  • Java - 泛型 + JUnit
  • vue3实现包含表格的Word文件导出
  • 【深度学习】TTS,CosyVoice,推理部署的代码原理讲解分享
  • flask高频面试题
  • 尚硅谷谷粒商城项目笔记——五、使用docker安装mysql
  • filebeat + logstash使用笔记
  • 学校考场电子钟设置自动开关机,节能环保
  • 短剧APP系统开发带来了哪些发展空间?
  • PaddlePaddle / PaddleOCR踩坑记,动手实现一个OCR服务器
  • JeecgBoot低代码平台简单记录
  • 零基础入门转录组数据分析——机器学习算法之xgboost(筛选特征基因)
  • C#开发常见面试题三(浅复制和深复制的区别)
  • Linux/C 高级——Linux命令
  • 怎么在 tailwindcss 项目中自定义一些可复用的样式