为了账号安全,请及时绑定邮箱和手机立即绑定

按值或引用存储 net.Conn?

按值或引用存储 net.Conn?

Go
眼眸繁星 2022-10-24 16:51:27
我的应用程序使用 async.Map来存储通过多个 goroutine 同时访问的打开的套接字连接。我想知道是将这些连接存储为结构net.Conn还是引用*net.Conn。这两种选择的优点/缺点是什么?首选的解决方案是什么?
查看完整描述

1 回答

?
侃侃尔雅

TA贡献1801条经验 获得超15个赞

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

sync.Map类型被明确定义为在 上进行操作interface{}

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

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

从表面上看,这两种方法在使用的空间方面都差不多,但请容忍我。
要存储指向容器数据类型(net.Conn例如sync.Map编译器安排确保原始net.Conn值直接在堆上分配。

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

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


话虽如此,我建议不要完全放弃在容器中存储指针,例如sync.Map:偶尔它会派上用场——例如,为了将数组重用于切片,您通常存储指向此类数组的第一个元素的指针。


查看完整回答
反对 回复 2022-10-24
  • 1 回答
  • 0 关注
  • 74 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信