golang 什么时候应该用 slices 或者 slices 的指针

Everything in Go, ever, always, is passed by value

与 C 语言家族的所有语言一样,Go 语言中的所有内容都是通过值传递的。也就是说,函数总是获得被传递内容的副本,就像有一条赋值语句将值赋给参数一样。例如,向函数传递一个 int 值会得到 int 的副本,传递一个指针值会得到指针的副本,但不会得到指针指向的数据。(关于这对方法接收器的影响,请参阅后面章节的讨论)。

映射和切片值的行为类似指针:它们是描述符,包含指向底层映射或切片数据的指针。复制映射或切片值并不会复制其指向的数据。复制接口值则是复制接口值中存储的内容。如果接口值包含一个结构体,复制接口值就会复制该结构体。如果接口值保存的是指针,复制接口值就会复制指针,但不会复制指针指向的数据。

参考代码测试结果: colobu.com/2016/10/28/...

Slices vs pointers to slices (如何选择)

从逻辑上讲,Slices 是一个由三个字段组成的结构体:

  • 一个指向片段后备数组的指针(该数组实际包含片段的元素)和两个 ints:
  • Slices 的容量
  • Slices 的长度

在传递和分配 Slices 值时,这些结构值会被复制:一个指针和两个整数。 正如你所看到的,当你传递一个 Slices 值时,后备数组不会被复制,只有一个指向它的指针。

也就是说,在 Slices 值传值过程的设计上,本身就是很轻量的,只复制了一个指针(的值),并没有复制全部数据。

现在,让我们考虑一下什么时候需要使用普通 Slices 或指向 Slices 的指针。

如果您担心性能(复制内存所需的内存分配和/或CPU周期),那么这些担忧是没有根据的: 在传递切片时复制三个整数在当今的硬件上非常便宜。使用指向 slice 的指针会使复制速度加快一点点------复制单个整数而不是三个整数------但是这些节省很容易被两个事实所抵消:

  • 几乎可以肯定,slice 的值最终会在堆上分配,这样编译器就可以确保它的值在跨越函数调用边界时仍然存在------这样您将为使用内存管理器付费,而垃圾收集器将承担更多的工作。

  • Using a level of indirection reduces data locality: 访问RAM的速度很慢,所以cpu有缓存,可以在读取数据的地址后面预取数据。如果控制流立即在另一个位置读取内存,那么预取的数据将被丢弃:缓存垃圾。

那么有没有一种情况下你想要一个指向切片的指针?是的。例如, built-in append 函数被定义为:

go 复制代码
func append(*[]T, T...)

而不是

scss 复制代码
func append([]T, T...) []T

(注意:这里的"T"实际上意味着"任何类型",因为"append"不是一个库函数,不能在普通 Go 中合理地定义;这是一种伪代码。)

也就是说,它可以接受指向切片的指针,并可能 替换 指针指向的切片,因此您可以将其定义为为 append(&slice, element) 而不是 slice = append(slice, element)

当你需要直接操作增删一个 slice ,并且用操作后的 slice,替换原来的 slice,这个时候可以像 append 一样,最好是使用指针。

其他的情况,不用指针。

但老实说,在我处理过的真实Go项目中,我记得使用指针指向片的唯一情况是为了池化大量重用的片,以节省内存重新分配。那个唯一的例子只是因为 sync.Pool keeping elements of type interface{} 这在使用指针时可能更有效。

Slices of values vs slices of pointers to values (关于这个话题其实和上面没有区别)

参考: stackoverflow.com/questions/7...

相关推荐
Victor3568 小时前
MongoDB(2)MongoDB与传统关系型数据库的主要区别是什么?
后端
JaguarJack8 小时前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端·php·服务端
BingoGo8 小时前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端
Victor3569 小时前
MongoDB(3)什么是文档(Document)?
后端
牛奔11 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌15 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
KYGALYX17 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了17 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法17 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
Moment18 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端