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文档设置纸张方向、大小和页边距统一设置格式插入文本插入表格插入图片 结语 前言 工作中有大量的报告编写需求,在不停地复制粘贴之后,突然想到,这种高…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
