go - 按值或引用存储 net.Conn?

标签 go goroutine

我的应用程序使用 sync.Map 来存储通过多个 goroutine 并发访问的打开套接字连接。

我想知道是将这些连接存储为结构体 net.Conn 还是引用 *net.Conn

这两种选择的优点/缺点是什么?首选解决方案是什么?

最佳答案

虽然@blackgreen 是正确的,但我会稍微扩展一下推理。

sync.Map类型被显式定义为在 interface{} 上运行.

现在请记住,在 Go 中,接口(interface)不仅仅是类型系统使用的抽象;它也是类型系统使用的抽象。相反,您可以拥有接口(interface)类型的值,这些值在内存中的表示形式是 struct包含两个指针:一个指向描述变量中存储的值的动态类型的内部对象,另一个指向该值本身(或运行时在堆上创建的它的副本)。

这意味着,如果您要存储指向 sync.Map 中任何内容的指针,任何存储的此类指针都将被转换为 interface{} 类型的值。它会在 sync.Map 中占据完全相同的空间。 .
相反,如果您要存储 net.Conn 类型的值直接在那里,它们会被直接存储——只是因为它们已经是接口(interface)值,所以 Go 只会复制这对指针。

从表面上看,这两种方法在使用的空间方面似乎是相同的,但请耐心等待。
存储指向 net.Conn 的指针容器数据类型中的值,例如 sync.Map ,程序必须确保该值分配在堆上(而不是直接将其分配在当前运行的 goroutine 的堆栈上),这一事实可能会迫使编译器进行安排,以确保原始 net.Conn值直接在堆上分配。

换句话说,存储指向接口(interface)类型变量的指针可能(并且通常会——由于典型代码的组织方式)在内存使用方面更加浪费。

此外,大多数解引用(指针追逐)往往会破坏 CPU 缓存;这不会改变游戏规则,但当您在紧密循环中迭代集合时,可能会增加几微秒的时间。


话虽如此,我建议不要彻底放弃将指针存储在像 sync.Map 这样的容器中。 :偶尔它会派上用场,例如,要重用 slice 数组,您通常存储指向此类数组的第一个元素的指针。

关于go - 按值或引用存储 net.Conn?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70754495/

相关文章:

go - 在golang中 sleep 会阻止其他goroutine吗?

go - 如何用逗号和 2 位小数格式化货币?

Golang协程错误 "all goroutines are asleep - deadlock!"

go - 如何编辑埋在递归结构中的数组

go - 使用 Go 更新 DynamoDB 中的多个值

go - channel 缓冲区在没有 goroutines 的情况下(在其范围内)与传递给 goroutines 时如何在 golang 中工作?

for-loop - for 循环中的 goroutines 问题

go - 如何使用 goroutines 接收数据并发回信号

go - 测试内存消耗

Golang,类型为字符串的变量