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

相关推荐
凡人的AI工具箱1 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
是店小二呀1 小时前
【C++】C++ STL探索:Priority Queue与仿函数的深入解析
开发语言·c++·后端
canonical_entropy1 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
我叫啥都行2 小时前
计算机基础知识复习9.7
运维·服务器·网络·笔记·后端
无名指的等待7123 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴3 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
AskHarries4 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端
苹果酱05674 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱5 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
计算机学姐7 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea