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

news2024/11/13 7:59:17

目录

一.引言

二.接收者类型

三.代码示例

1.指针接收者

2.值接收者

3.运行结果对比

4.代码修改

5.刨根问底

四.总结


一.引言

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

二.接收者类型

  • 指针接收者 (*Type):

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

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

三.代码示例

1.指针接收者

package main

import "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 main

import "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 main

import "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 main

import "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 main

import "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.coloradmin.cn/o/1986887.html

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

相关文章

scratch水仙花数 2024年6月scratch四级 中国电子学会图形化编程 少儿编程等级考试四级真题和答案解析

目录 scratch水仙花数 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、p…

深度学习入门(一):感知机与输入数据

单层感知机与多层感知机 单层感知机(Single-Layer Perceptron)和多层感知机(Multi-Layer Perceptron,简称MLP)是神经网络的基本形式,用于执行各种机器学习任务,包括分类和回归。它们都基于早期…

赚他10个亿...

体育竞技 & 商业价值 虽然昨天遭受了全球黑一,但四年一度的奥运会还是要关注的。 不知道最近大家是否有关注巴黎奥运会,印象深刻的项目又是哪个? 截止于发稿前,目前「金牌榜」上,中国以微弱优势位于第一&#xff0…

CDGA/CDGP数据治理证书:含金量高,职场竞争力提升的明智之选

在当今这个数据驱动的时代,数据已成为企业最宝贵的资产之一,而高效、合规的数据治理则是挖掘数据价值、驱动业务增长的关键。随着企业对数据治理重视程度的不断提升,拥有专业数据治理知识和技能的人才变得尤为稀缺。在此背景下,CD…

win10批量修改文件名,记得保存文件

打开需要修改的文件夹新建文本内容如下 DIR . /B>文件列表.csv 并另存为bat文件,注意编码,双击bat文件生成Excel 打开Excel 填写你的文件名至B列,如我需要在文件名前面都加上spi5_公式D1&A1 C列输入"REN "&"""&q…

【C++BFS算法】2059. 转化数字的最小运算数

本文涉及知识点 CBFS算法 LeetCode2059. 转化数字的最小运算数 给你一个下标从 0 开始的整数数组 nums ,该数组由 互不相同 的数字组成。另给你两个整数 start 和 goal 。 整数 x 的值最开始设为 start ,你打算执行一些运算使 x 转化为 goal 。你可以…

实验8-1-7 数组循环右移

本题要求实现一个对数组进行循环右移的简单函数:一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据 (最后m个数循环移至最前面的m个位置)…

CMU15445 (Fall 2023) Project 4 - Concurrency Control 思路分享

文章目录 写在前面Task 1 - Timestamps1.1 Timestamp Allocation1.2 Watermark Task 2 - Storage Format and Sequential Scan2.1 Tuple Reconstruction2.2 Sequential Scan / Tuple Retrieval Task 3 - MVCC Executors3.1 Insert Executor3.2 Commit3.3 Update and Delete Exe…

FreeIPA安装

一、环境准备 主机名IP角色master. bhlu. com192.168.22.10服务端node1. bhlu. com192.168.22.11客户端 两台服务器关闭防火墙和 selinux配置好 yum 源 1.1 配置 chronyd 配置好 chronyd,使用 chronyc source -v 可以验证 # 这里写了一个playbook作为示例了 --…

OpenHarmony网络请求库-axios

简介 Axios ,是一个基于 promise 的网络请求库,可以运行 node.js 和浏览器中。本库基于 Axios 原库v1.3.4版本进行适配,使其可以运行在 OpenHarmony,并沿用其现有用法和特性。 http 请求Promise APIrequest 和 response 拦截器转…

Codeforces Round 920 (Div. 3) A~E 题

A. Square 题目链接: Problem - A - Codeforces 思路: 题目比较简单:就是给你一个矩形的四个顶点的坐标,然后让你求矩形的面积,我们知道矩形的面积等于长乘宽,那么,如何就矩形的长和宽&…

ctfhub Bypass disable_function

LD_PRELOAD url 蚁剑连接 选择插件 点击开始 查看到此文件名编辑连接拼接到url后面重新连接 点击开启终端 在终端执行命令 ls / /readfile ShellShock url CTFHub 环境实例 | 提示信息 蚁剑连接 写入shell.php <?phpeval($_REQUEST[ant]);putenv("PHP_test() { :…

ViT论文详解

文章目录 前言一、ViT理论二、模型结构三、实验结果总结 前言 ViT是谷歌团队在2021年3月发表的一篇论文&#xff0c;论文全称是《AN IMAGE IS WORTH 16X16 WORDS:TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE》一张图片分成16x16大小的区域&#xff1a;使用Transformer进行按比…

如何将Python程序打包成exe程序

众所周知,通过python开发的程序要运行,一般需要安装python环境来运行程序文件,那么如何在未安装python环境的电脑上直接运行程序呢?通常采用Pyinstaller来实现的,本文主要对该打包过程进行具体说明。本文重点解决PyQt5在打包时无法正确运行的问题。 一、安装Pyinstaller 安…

Docker常用命令与相关操作(更新中)

Docker介绍 1.什么是Docker Docker是一个开源的应用容器引擎&#xff0c;它是一个是基于Go语言开发的开源项目。使用Docker可以让开发者封装他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任意的Linux机器上&#xff0c;也可以实现虚拟化。Docker容器完全使…

机房空调远程控制方案

概述 企业和园区都会有电力机房&#xff0c;往往会配备抽风机或者空调设备。特别在南方&#xff0c;空气湿度大时特别需要这些设备。经常有业主反馈&#xff0c;下班后靠人力到现场控制不太方便&#xff0c;24小时开启又浪费资源&#xff0c;而且可能有长期噪声污染。为此&…

Tomato靶机

修改网络模式为NAT 主机发现 arp-scan -l 端口扫描 nmap 192.168.48.147 nmap -sC -sV -O 192.168.48.147 -sC常见漏洞脚本扫描 -sV开放端口服务/版本号 -O操作系统探测 端口利用 访问web服务 目录扫描 dirb http://192.168.48.147 访问 http://192.168.48.147/antibot_im…

盘点4款令人惊艳的视频剪辑工具

在这个短视频盛行的时代&#xff0c;每个人都可以成为视频内容的创作者。但是&#xff0c;在此之前&#xff0c;拥有一款适合自己的剪辑软件十分重要。今天我就来和大家来说一说我自己觉得比较好用的4款剪辑软件。 1、福昕剪辑神器 直达链接&#xff1a;www.pdf365.cn/foxit-c…

如何将iphone照片导入电脑?4种使用的照片导入办法

你是否曾为如何将iPhone上的照片导入电脑而烦恼&#xff1f;是否尝试过多种方法&#xff0c;却总是觉得步骤繁琐、效率低下&#xff1f;不用再为找不到好方法而挠头了&#xff01; 下面分享几种实用的导入办法&#xff0c;让你在短时间内将照片从iPhone照片导入电脑&#xff0…