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...

相关推荐
用户1474853079741 小时前
CodeX使用Skill生成游戏美术和音乐资源,一分钟入门
后端
Melody1231 小时前
用 abort 中断 AI 流式请求,我之前做错了
后端
onething3652 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 5 —— SSE 流式输出 + 打字机效果
人工智能·后端·全栈
一个做软件开发的牛马2 小时前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
码事漫谈2 小时前
AI 编程的「三体」架构:OpenSpec + Superpowers + GStack 如何让一个开发者撑起整个研发团队
后端
吃饱了得干活2 小时前
深入解析 OpenFeign:从重试、拦截到负载均衡的全维度实践
后端
onething3652 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 6 —— 业务完善 + 会话消息预览
人工智能·后端·全栈
BingoGo3 小时前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack3 小时前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
IT_陈寒3 小时前
SpringBoot自动配置的坑,我爬了三天才出来
前端·人工智能·后端