Go Slice/Map 复制陷阱

信的内容是我 22 年问 Google Golang Nuts 的问题以及得到的回复,原信链接:https://groups.google.com/g/golang-nuts/c/Q7_Dj_ogVJE/m/_5TSXCIaBgAJ?pli=1

信件内容

为什么Go的slice有“复制陷阱”,而map却没有?

假设我们有一个以 slice 作为输入参数的函数,如果在函数中展开 slice,则只会改变复制的 slice 结构,而不是原来的 slice 结构。原来的slice仍然指向原来的数组,而函数中的slice因为扩容而改变了数组指针。
在这里插入图片描述

看一下输出,如果slice是通过“引用”传递的,它就不会是[1 2]。再看这个例子:
在这里插入图片描述
我们在 domap() 中完成的操作成功了!

这难道是陷阱吗?!

我的意思是,map是通过“引用”(*hmap) 传递的,slice是通过“值”(SliceHeader) 传递的。

为什么map和slice被设计成都是内部引用类型,为什么这么不一致呢?

也许这只是一个设计问题,但为什么呢?为什么要这样slice和map?


以下是我对证明为什么map只能通过“引用”传递的猜测:

假设map是按值传递的-> hmap结构类型

(1)init之后:(函数外的hmap)

hmap.buckets = bucketA
hmap.oldbuckets = nil

(2)传递param后,进入函数:(函数内的hmap)

hmap.buckets = bucketA
hmap.oldbuckets = nil

(3)触发扩容后:(函数内的hmap)

hmap.buckets = bucketB
hmap.oldbuckets = bucketA

但slice不一样!

没有增量迁移,也没有oldbuckets, 所以可以使用结构体,因为函数与外部隔离,而map则不然,oldbuckets是在函数外部引用的。

我的意思是,这样设计的最初目的可能是传值,防止直接修改函数中的原始变量,但是map不能传值。一旦将值传递给map,在函数内执行扩容的过程中原始map的数据就会丢失。

如果有人能帮助我解决这个问题,我将不胜感激。多谢!

(我为我垃圾的中式英语感到抱歉,我希望我把问题说清楚了…😢这真的让我很困扰…)

golang-nuts的回信

已经翻译成中文了

@Brian Candler

(顺便说一句:请不要发布屏幕截图。纯文本更易于阅读,并且可以复制粘贴。您也可以使用 https://go.dev/play/ 粘贴代码片段)

我想你已经很好地理解了这个问题。来自 https://golang.org/src/runtime/slice.go 的源代码:

type slice struct {array unsafe.Pointerlen   intcap   int
}

正如您所发现的,这是按值传递的。如果你愿意,当然可以显式传递指向此类值的指针。

这是陷阱吗?!

嗯,这是你必须学习的语言知识,但我认为这是可用设计选项中的最佳选择。

string 和 slice 彼此一致:它们是普通结构,包含指向数据的指针、长度和容量(对于slice)。

是否可以实现值始终是指向结构的“指针”的 slice 和 string ?

我想应该是可以的,但我认为在更深层次上你仍然会遇到类似的问题。

当复制 slice (b := a) 或将其作为函数参数传递时,这将会复制一个指针,因此同一个 slice 将有两个别名,并且对一个slice的修改将对另一个也可见。但是,当进行子切片 (b := a[1:2]) 时,将被迫分配一个新的slice结构。

因此,slice 的行为将完全取决于它的生成方式,因此改变slice可能会也可能不会影响其他slice。我认为整体上会更加混乱。

最重要的是,你仍然会遇到与今天相同的问题:

两个slice可能会也可能不会共享相同的底层缓冲区。

map和channel彼此一致:它们都有比较大的数据结构,并且值是指向该结构的指针。我认为将map值设置为指针是有充分理由的;这意味着你可以做一些方便的事情,比如:

m["foo"] = "bar"

而不是:

m = m.set("foo", "bar") // compare: s = append(s, "foo")

但另一方面,map或channel的零值并不是很有用:它是一个 nil 指针,它告诉您有零个元素,但不能添加任何元素。这使得它们在构建包含这些内容的结构时不方便,因为您需要显式地 make(…) 。这是 Go 新手抱怨的另一件事。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619637.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软拼音输入法删除备选词

不是所有词都可以从微软拼音输入法的备选词中删除的。 当你需要对自己的自定义词删除的话,在备选词中选择鼠标右键,然后单击删除。 如上图就可以把备选词从微软拼音输入法中删除了。

【SpringBoot】返回参数

返回参数 返回页面返回数据返回 html 代码返回 json 数据两数相加用户登录 返回页面 首先在 static 文件夹中创建 index.html 文件&#xff1a; 代码&#xff1a; <html> <body><h1>hello word!!!</h1><p>this is a html page</p> <…

从 SQLite 3.5.9 迁移到 3.6.0(二十一)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;从 SQLite 3.4.2 迁移到 3.5.0&#xff08;二十&#xff09; 下一篇&#xff1a;SQLite从出生到现在&#xff08;发布历史记录&#xff09;&#xff08;二十二&#xff09; ​SQLite 版本 3.6.0 &#xff08;2008…

【MATLAB源码-第16期】基于matlab的MSK定是同步仿真,采用gardner算法和锁相环

1、算法描述 **锁相环&#xff08;PLL&#xff09;** 是一种控制系统&#xff0c;用于将一个参考信号的相位与一个输入信号的相位同步。它在许多领域中都有应用&#xff0c;如通信、无线电、音频、视频和计算机系统。锁相环通常由以下几个关键组件组成&#xff1a; 1. **相位…

PostgreSQL入门到实战-第二十七弹

PostgreSQL入门到实战 PostgreSQL中数据分组操作(二)官网地址PostgreSQL概述PostgreSQL中HAVING命令理论PostgreSQL中HAVING命令实战更新计划 PostgreSQL中数据分组操作(二) 使用PostgreSQL HAVING子句来指定组或聚合的搜索条件 官网地址 声明: 由于操作系统, 版本更新等原因…

华为OD机试 - 内存冷热标记(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

经久耐用特氟龙材质塑料烧杯PFA坩埚耐受强酸强碱耐高温

PFA烧杯在实验过程中可作为储酸容器或涉及强酸强碱类实验的反应容器&#xff0c;用于盛放样品、试剂&#xff0c;可搭配电热板加热、蒸煮、赶酸用。 PFA烧杯规格参考&#xff1a;10ml、30ml、50ml、100ml、250ml、500ml、1000ml、2000ml。 外壁均有凸起刻度&#xff0c;直筒设…

《由浅入深学习SAP财务》:第2章 总账模块 - 2.6 定期处理 - 2.6.6 年初操作:科目余额结转

2.6.6 年初操作&#xff1a;科目余额结转 在使用事务代码 FAGLB03 查询科目余额时&#xff0c;可以看到按期间的发生额清单。其中&#xff0c;第一行称为“余额结转”&#xff0c;该行的累计余额代表上年度遗留下来的余额&#xff0c;也就是年初余额。对于资产负债表科目而言&a…

高清4路HDMI编码器JR-3214HD

产品简介&#xff1a; JR-3214HD四路高清HDMI编码器是专业的高清音视频编码产品&#xff0c;该产品具有支持4路高清HDMI音视频采集功能&#xff0c;4路3.5MM独立外接音频输入&#xff0c;编码输出双码流H.264格式&#xff0c;音频MP3/AAC格式。编码码率可调&#xff0c;画面质…

2024最新 PyCharm 2024.1 更新亮点看这篇就够了

2024最新 PyCharm 2024.1 更新亮点看这篇就够了 文章目录 2024最新 PyCharm 2024.1 更新亮点看这篇就够了&#x1f680; PyCharm 2024.1 发布&#xff1a;全面升级&#xff0c;助力高效编程&#xff01;摘要引言 &#x1f680; 快速掌握 Hugging Face&#xff1a;模型与数据集文…

武汉星起航助力跨境电商,专业选品与全方位服务引领行业新风尚

在全球跨境电商浪潮的推动下&#xff0c;越来越多的卖家纷纷将目光投向了这片广阔的市场。然而&#xff0c;如何在这片蓝海中脱颖而出&#xff0c;成为众多卖家关注的焦点。武汉星起航电子商务有限公司以其专业的选品建议和全方位的服务&#xff0c;为卖家们提供了一条成功的捷…

通讯录的实现(单链表版本)

我们首先要知道通讯录的实现是基于单链表的基础上的&#xff0c;所以我们首先要搞懂单链表。&#xff08;注意&#xff1a;今天的代码量较多&#xff09;&#xff0c;但这不是阻挡我们前进的脚步&#xff0c;冲冲冲&#xff01;&#xff01;&#xff01; 单链表的简要概述 我们…