golang中的值传递与引用传递,如何理解结构体的方法?
先从一个例子说起
type Counter struct {count int
}func (c Counter) Inc() {c.count++
}func test1() {c := Counter{}do := func() {for i := 0; i < 10; i++ {c.count++}fmt.Println("done")}go do()go do()time.Sleep(3 * time.Second)fmt.Println(c.count)
}func test2() {c := Counter{}do := func() {for i := 0; i < 10; i++ {c.Inc()}fmt.Println("done")}go do()go do()time.Sleep(3 * time.Second)fmt.Println(c.count)
}
结果:test1() 打印20,test2() 打印0
现在焦点放在 test2() 上。
有人说,Inc() 方法的定义应该使用结构体指针,是的,答案的确如此,但是这底层的原因是什么呢?
对于普通的函数,我们很容易就知道是否需要传入指针,比如
func f1(obj *Counter)
func f2(obj Counter)
实际上,我们将结构体的方法做个反射就会发现
type Counter struct {count int
}func (c Counter) Inc() {c.count++
}func test3() {c := Counter{}reflectValue := reflect.TypeOf(c)fmt.Println(reflectValue.Method(0).Type)
}
打印:func(main.Counter)
或者
type Counter struct {count int
}func (c *Counter) Inc() {c.count++
}func test3() {c := &Counter{}reflectValue := reflect.TypeOf(c)fmt.Println(reflectValue.Method(0).Type)
}
打印:func(*main.Counter)
所以在调用结构体的方法时,c.Inc(),实际上是Inc(c),这样一来,我们就很容易知道该使用Counter还是*Counter来定义Inc()。
还是最开始的代码,没有做修改,我们在Inc中打印c的地址
func (c Counter) Inc() {fmt.Printf("%p\n", &c)c.count++
}
执行test2,打印如下
0xc0000a6058
0xc0000a60a0
0xc0000a60a8
0xc0000a60b0
0xc0000a60b8
0xc0000a60c0
0xc0000a60c8
0xc0000a60d0
0xc0000a60d8
0xc0000a60e0
0xc00001c050
done
0xc000102000
0xc0000a60e8
0xc0000a6100
0xc0000a6108
0xc0000a6110
0xc0000a6118
0xc0000a6120
0xc0000a6128
0xc0000a6130
done
0
可见每一次执行Inc,c的地址都不一样,这是因为do函数中的c只是外面的c的一个拷贝。
修改后的代码
func (c *Counter) Inc() {fmt.Printf("%p\n", c)c.count++
}
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
0xc0000a6058
done
done
20
将 test2() 中的c := &Counter{}改成c := &Counter{},打印信息依旧正确,这是因为golang会根据Inc的定义,自动决定传入Counter或者*Counter进去。
如果将count int换成map或者slice就是另外的情况了,因为这两个类型本身就是引用类型,你不需要显示的声明*,它们就是以引用来工作的。
当函数参数比较大时,使用指针类型可以避免数据拷贝,提升效率。但是使用指针需要注意连贯性,也就是说后续都应该使用指针,否则这个变量就是混乱的。
在Go的 FAQ 中也有关于这一话题的阐述。
参考
Beware of copying mutexes in Go
Should I define methods on values or pointers?
相关文章:
golang中的值传递与引用传递,如何理解结构体的方法?
先从一个例子说起 type Counter struct {count int }func (c Counter) Inc() {c.count }func test1() {c : Counter{}do : func() {for i : 0; i < 10; i {c.count}fmt.Println("done")}go do()go do()time.Sleep(3 * time.Second)fmt.Println(c.count) }func te…...
linux部署ansible自动化运维
ansible自动化运维 1,编写ansible的仓库(比赛已经安装,无需关注) 1、虚拟机右击---设置---添加---CD/DVD驱动器---完成---确定 2、将ansible.iso的光盘连接上(右下角呈绿色状态) 3、查看光盘挂载信息 df -h…...
docker—私有仓库搭建
docker—私有仓库搭建 HTTP 部署 docker run -d \-p 5000:5000 \--restartalways \--name registry \-v /opt/data/registry:/var/lib/registry \registry:2使用官方的 registry 镜像来启动私有仓库。默认情况下,仓库会被创建在容器的 /var/lib/registry 目录…...
【SpringAOP】深入浅出SpringAOP从原理到源码
AOP对象是如何创建的 对于熟悉Spring IOC流程源码的同学来说,一定了解bean的整个生命周期,也就是从实例化、属性填充、初始化三个过程。那么对于Bean 工厂来说,是如何保证需要创建代理的对象创建代理的呢。 从图中可以看到,本质…...
Java 从查询超时到性能提升 (实战讲解)
目录 1. 问题所示2. 原理分析3. 解决方法3.1 代码优化3.2 索引优化3.3 删数据 1. 问题所示 查询返回速度慢,导致前端页面无数据显示 前端和后端均未报错,但后端未能在合理时间内返回结果到前端 后端没有报错日志 2. 原理分析 单独分析代码中的对算法…...
《C 语言携手 PaddlePaddle C++ API:开启深度学习开发新征程》
在深度学习领域,PaddlePaddle 作为一款强大的深度学习框架,为开发者提供了丰富的功能和高效的计算能力。而 C 语言,凭借其高效性和广泛的应用场景,与 PaddlePaddle 的 C API 相结合,能够为深度学习开发带来独特的优势。…...
Mysql之存储过程
MySQL 存储过程(Stored Procedure) 1. 概念 存储过程是一组预编译的 SQL 语句集合,可以通过调用名称来执行。存储过程可以接收参数,并支持复杂的业务逻辑(如条件语句、循环、异常处理等)。它们可以提高代…...
XV6 开发环境搭建
Step 1 搭建ubuntu 20.04 虚拟机 注意:一定要使用ubuntu 20.04,该版本可以直接通过deb安装gnu编译工具链。 安装完虚拟机后,换apt源。 ubuntu20.04镜像下载链接 设置root账户密码: sudo passwd root Step 2 下载解压qemu 5.1.0 wget ht…...
Windows 系统下 Python 环境安装
一、引言 Python 作为一种广泛应用的编程语言,在数据分析、人工智能等领域发挥着重要作用。本文将详细介绍在 Windows 系统上安装 Python 环境的步骤。 二、安装前准备 系统要求 Windows 7 及以上版本一般都能支持 Python。硬件方面,通常 2GB 内存、几…...
VMware Workstation的有线连接消失了
进入/var/lib目录下 cd /var/lib 查看是否存在NetworkManager 文件 ls 将其删除,然后虚拟机reboot一下。 sudo rm -r NetworkManager reboot 解决了,可以联网...
73页车企大数据平台规划与数据价值挖掘应用咨询项目方案解读
该项目旨在帮助乘用车公司规划大数据平台并提高数据挖掘应用水平,以满足业务部门对数据的需求,同时保证数据完整性和真实性。数据应用体系现状存在数据孤岛和数据关注维度不统一的问题,导致业务部门无法便捷使用数据并无法进行业务预测。大数…...
MIF格式详解,javascript加载导出 MIF文件示例
MIF 格式详解 MIF(MapInfo Interchange Format)是由Pitney Bowes Software开发的一种文本格式,用于存储地理空间数据。它通常与地图可视化和地理信息系统(GIS)相关联。MIF文件通常成对出现,一个.mif文件用…...
若依实现图片上传时自动添加水印
文章目录 总体思路1. 修改通用上传方法2. 去除文件路径前两级目录3. 添加水印方法运行效果总结 为了解决图盗用,并有效保护图片版权,若依项目需要实现一个功能:上传图片时,自动在图片上添加水印。这不仅可以有效防止盗用ÿ…...
用于日语词汇学习的微信小程序+ssm
日语词汇学习小程序是高校人才培养计划的重要组成部分,是实现人才培养目标、培养学生科研能力与创新思维、检验学生综合素质与实践能力的重要手段与综合性实践教学环节。本学生所在学院多采用半手工管理日语词汇学习小程序的方式,所以有必要开发日语词汇…...
【信息系统项目管理师】高分论文:论信息系统项目的范围管理(融媒体发布系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 正文1、规划范围管理2、收集需求3、定义范围4、创建WBS5、确认范围6、控制范围正文 我市xx社区作为智慧社区建设的试点社区,将通过各种创新技术手段,促进小区公共服务智能管理应用,实现社区中的基础设施、环…...
Kaggler日志--Day5
进度24/12/15 昨日复盘 Intermediate Mechine Learning之类型变量 读两篇讲解如何提问的文章,在提问区里发起一次提问 实战:自己从头到尾首先Housing Prices Competition for Kaggle Learn Users并成功提交 Intermediate Mechine Learning之管道&#…...
VScode MAC按任意键关闭终端 想要访问桌面文件
说明 最近配置MAC上CPP的运行环境,在安装必要的CPP插件后,配置launch和task等json文件后,点击运行三角形,每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台,非常逆天。 尝试 尝试1:尽管我尝试将ta…...
小粑记故乡的记忆
小粑,是我的故乡一安徽池州一带盛行的小吃。约成人掌心大小,厚度只三、四厘米,故谓之“小”。 小粑,主打取材随性,方便常做常吃。这也许就是它抓住人的味蕾,渐次流行开来,成为当地名小吃的主要原…...
git使用小记
环境(centos为例): yum -y install gitmkdir git_dir && cd git_dirgit clone *** 修改代码: git checkout master 切到主分支git pull 拉取最新代码git branch dev 创建开发分支git checkout dev 切换到开发分支修…...
Python实现办公自动化——自动编写word文档
Python实现办公自动化——自动编写word文档 前言安装python-docxpython-docx使用创建word文档设置纸张方向、大小和页边距统一设置格式插入文本插入表格插入图片 结语 前言 工作中有大量的报告编写需求,在不停地复制粘贴之后,突然想到,这种高…...
告别CNN局部视野:用UNETR的Transformer编码器搞定三维医学图像分割(附PyTorch+MONAI实战)
突破CNN局限:UNETR在三维医学图像分割中的Transformer实践指南 医学图像分割一直是计算机辅助诊断系统中的核心环节,从肿瘤定位到器官轮廓勾画,精准的分割结果直接影响后续分析的可靠性。传统基于CNN的方法虽然在2D图像处理中表现出色&#x…...
别再只算差异了!用Cytoscape给Hub Gene分析加个‘可视化Buff’(附脑网络实战图)
别再只算差异了!用Cytoscape给Hub Gene分析加个‘可视化Buff’(附脑网络实战图) 在生物信息学分析中,差异基因筛选往往是研究的第一步,但如何从海量差异基因中找出真正具有生物学意义的"关键调控者"…...
人工智能在科学领域需要设立防护措施,避免对它不加批判地采用
耶鲁大学人类学研究生院主任Lisa Messeri、和普林斯顿大学的心理学家M. J. Crockett 发给《自然》期刊的论文中阐述:人工智能正在迅速加速科学产出,但也有可能缩小研究范围,削弱判断力,削弱科学家的培训方式。科学界正以惊人的速度…...
固始汽车贴膜口碑榜:前3名都有谁?
老铁们,最近固始的车友群里吵翻了,都在问“固始汽车贴膜哪家好”。十个有八个刚提了新车,第一个想到的就是去贴个膜,但这一脚踩下去,水深得很。我直接跟你们说个扎心的事实:固始街头随便找家店,…...
2026毕业答辩PPT模板实测:三个平台的真实体验与避坑建议
又到毕业答辩季,不少同学论文写完了,却被PPT卡住:排版乱、配色杂、结构不清,明明内容扎实,呈现效果却大打折扣。作为经常接触办公工具的博主,我实测了几个常见的PPT模板与制作平台,重点针对本科…...
技术人的人际关系:建立良好的职业网络
技术人的人际关系:建立良好的职业网络 引言 作为一名技术人,人际关系同样重要。良好的人际关系可以帮助我们获得更多机会,提升职业发展。 今天就来分享一下如何建立良好的职业网络。 为什么人际关系重要 职业发展 良好的人际关系有助于职业发…...
ROCm rocr-libhsakmt分析系列3: aperture概念
前文 acquire_vm 讲了gpu vm的概念,gpu vm就是一个GPU虚拟地址空间。那么偌大的一个空间,我们该如何使用它呢?仍然可以类比进程的虚拟地址空间,例如,进程的虚拟地址空间按功能划分成了多个段:代码段、全局变量段、栈区、堆区、文件mmap区等,每个段占用互不相交的虚拟地址…...
基于STM32的温室大棚智能监控与无线调控系统设计
摘要:本设计了一种基于STM32的温室大棚智能监控系统。系统采用STM32F103作为主控芯片,集成DHT11温湿度传感器、土壤湿度传感器和C O2传感器实现环境参数采集。通过ESP32-C3 WiFi模块实现数据无线传输和远程控制,OLED屏幕进行本地显示。项目简…...
OpenAvatarChat终极部署指南:如何构建企业级数字人对话系统
OpenAvatarChat终极部署指南:如何构建企业级数字人对话系统 【免费下载链接】OpenAvatarChat 项目地址: https://gitcode.com/gh_mirrors/op/OpenAvatarChat OpenAvatarChat是一款革命性的模块化交互数字人对话框架,为开发者提供了从本地推理到云…...
claudecode用户如何通过taotoken解决封号与token不足的痛点
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 claudecode用户如何通过taotoken解决封号与token不足的痛点 1. 场景与核心挑战 对于深度使用 Claude Code 编程助手的开发者而言&…...
