- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章搞 Go 要了解的 2 个 Header,你知道吗?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
大家好,我是煎鱼.
在 Go 语言中总是有一些看上去奇奇怪怪的东西,咋一眼一看感觉很熟悉,但又不理解其在 Go 代码中的实际意义,面试官却爱问... 。
今天要给大家介绍的是 SliceHeader 和 StringHeader 结构体,了解清楚他到底是什么,又有什么用,并且会在最后给大家介绍 0 拷贝转换的内容.
一起愉快地开始吸鱼之路.
。
SliceHeader 如其名,Slice + Header,看上去很直观,实际上是 Go Slice(切片)的运行时表现.
既然知道了切片的运行时表现,那是不是就意味着我们可以自己造一个?
在日常程序中,可以利用标准库 reflect 提供的 SliceHeader 结构体造一个:
你认为输出结果是什么,这两个新切片会指向同一个底层数组的内存地址吗?
输出结果:
两个切片的 Data 属性所指向的底层数组是一致的,Len 属性的值不一样,sh1 和 sh2 分别是两个切片.
为什么两个新切片所指向的 Data 是同一个地址的呢?
这其实是 Go 语言本身为了减少内存占用,提高整体的性能才这么设计的.
将切片复制到任意函数的时候,对底层数组大小都不会影响。复制时只会复制切片本身(值传递),不会涉及底层数组.
也就是在函数间传递切片,其只拷贝 24 个字节(指针字段 8 个字节,长度和容量分别需要 8 个字节),效率很高.
这种设计也引出了新的问题,在平时通过 s[i:j] 所生成的新切片,两个切片底层指向的是同一个底层数组.
假设在没有超过容量(cap)的情况下,对第二个切片操作会影响第一个切片.
这是很多 Go 开发常会碰到的一个大 “坑”,不清楚的排查了很久的都不得而终.
。
除了 SliceHeader 外,Go 语言中还有一个典型代表,那就是字符串(string)的运行时表现.
可得知 “Hello” 字符串的底层数据如下:
底层的存储示意图如下:
真实演示例子如下:
你认为输出结果是什么,变量 s 和 s1、s2 会指向同一个底层内存空间吗?
输出结果:
从输出结果来看,变量 s 和 s1 指向同一个内存地址。变量 s2 虽稍有偏差,但本质上也是指向同一块.
因为其是字符串的切片操作,是从第 7 位索引开始,因此正好的 17608234-17608227 = 7。也就是三个变量都是指向同一块内存空间,这是为什么呢?
这是因为在 Go 语言中,字符串都是只读的,为了节省内存,相同字面量的字符串通常对应于同一字符串常量,因此指向同一个底层数组.
。
为什么会有人关注到 SliceHeader、StringHeader 这类运行时细节呢,一大部分原因是业内会有开发者,希望利用其实现零拷贝的 string 到 bytes 的转换.
常见转换代码如下:
但这其实是错误的,官方明确表示:
the Data field is not sufficient to guarantee the data it references will not be garbage collected, so programs must keep a separate, correctly typed pointer to the underlying data. 。
SliceHeader、StringHeader 的 Data 字段是一个 uintptr 类型。由于 Go 语言只有值传递.
因此在上述代码中会出现将 Data 作为值拷贝的情况,这就会导致无法保证它所引用的数据不会被垃圾回收(GC).
应该使用如下转换方式:
在程序必须保留一个单独的、正确类型的指向底层数据的指针.
在性能方面,若只是期望单纯的转换,对容量(cap)等字段值不敏感,也可以使用以下方式:
性能对比:
会相当标准的转换性能会稍快一些,这种强转也会导致一个小问题.
代码如下:
输出结果:
这种强转其会导致 byte 的切片容量非常大,需要特别注意。一般还是推荐使用标准的 SliceHeader、StringHeader 方式就好了,也便于后来的维护者理解.
。
在这篇文章中,我们介绍了字符串(string)和切片(slice)的两个运行时表现,分别是 StringHeader 和 SliceHeader.
同时了解到其运行时表现后,我们还针对其两者的地址指向,常见坑进行了说明.
最后我们进一步深入,面向 0 拷贝转换的场景进行了介绍和性能分析.
你平时有没有遇到过这块的疑惑或问题呢,欢迎大家一起讨论.
参考 。
Go语言slice的本质-SliceHeader 。
数组、字符串和切片 。
零拷贝实现string 和bytes的转换疑问 。
原文链接:https://mp.weixin.qq.com/s/rGqM1wMlqQEoJSgyrgZNLg 。
最后此篇关于搞 Go 要了解的 2 个 Header,你知道吗?的文章就讲到这里了,如果你想了解更多关于搞 Go 要了解的 2 个 Header,你知道吗?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在让“@header”或任何其他@规则在ANTLR中工作时遇到麻烦。具有非常基本的语法,如下所示: grammar test; options { language = CSharp2;
我对来源和寄宿有疑问 我有一个ajax页面“Page A”,它将称为ajax提要“Page B” 我看到来自ajax调用的“页面B”的请求 header 具有源“http://mydomain.com
我在 pandas 中使用了数据透视表并获得了所需的数据框格式,但现在我有两行标题。数据透视表后的结果数据框如下: scenario Actual Plan
我在 pandas 中使用了数据透视表并获得了所需的数据框格式,但现在我有两行标题。数据透视表后的结果数据框如下: scenario Actual Plan
我想在主机将它们发送到网络之前修改数据包头(IP 头、TCP 头)。 例如,如果我使用 firefox 进行浏览,那么我想拦截所有来自 firefox 的数据包并修改 IP/TCP header ,然
我的 header 内容被包装到#header 中,但是当我设置边框显示结构时,它显示我的#header 的内容出现在#header 本身之后。可能是什么问题?这是我的代码: #header { bo
我是一名 Web 开发人员,使用过 PHP 和 .NET。有一年多的 Web 工作经验,我一直无法彻底了解浏览器缓存功能,希望这里的 Web Gurus 可以帮助我。我心中的问题是: 浏览器实际上是如
伙计们,我有一个问题,我不知道如何在一个 header 中连接多个 header ,我们称它为“主 header ”并使用该 header 中的函数,例如 // A.h #include class
我有一个包含 SOAP 消息的 XMLHTTPRequest。 我想添加用于标识消息并将由 C# Web 服务使用的 guid。 GUID 的目标是识别特定用户,并应护送所有用户请求以在服务器上进行身
我一直在阅读粘性标题,这是我目前所发现的。第一个粘性 header 效果很好,但是当它遇到第一个 header 时,我如何向上滚动第一个 header 并使第二个 header 卡住? http://
我想将当前基于 TableView 的数据网格转换为新的 UICollectionView 类。 这就是我当前的网格的样子: 我的网格有两个标题: 年份(2006a、2007a 等)和 类型(“收入”
我目前正在使用 Apollo 服务器。我正在尝试在响应 header 中设置一个属性。并且此属性是从客户端 graphQL 请求 header 中检索的。 我在网上查了一下。并看到了诸如使用插件或扩展
我的 Controller 的方法需要设置一个标题,例如X-Authorization .创建新对象( store Action )后,我执行转发以显示新创建的对象( show Action ): $
我正在研究一些关于 VLAN 的事情,发现了 VLAN 标签 和 header 。 如果我们有标准 802.3 以太网帧 的 MTU(1518 字节), header 802.3 中包含什么? 另外,
我是放心和 Java 的新手,我正在尝试做一个非常基本的测试来检查 API 的响应是否为 200 ok。 谁能告诉我我需要在下面的脚本中更改什么才能传递多个 header Id、Key 和 ConId
在我的项目中,我需要知道 zlib header 是什么样的。我听说它相当简单,但我找不到 zlib header 的任何描述。 例如,它是否包含魔数(Magic Number)? 最佳答案 zlib
我正在使用 JMeter 测试 HTTP 服务器,该服务器接受并验证 APIKey 并在成功时返回一个有时限的 token 。如果我有 token ,我想发送一个 token ;如果没有,我想发送一个
以太网 header 是什么样的? 是吗: 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|
我们的应用程序支持 CORS 配置 header 。我在两个不同的主机上分别配置了 testApp。两种设置都相互独立工作。host1 上的应用程序配置有 CORS header Access-Con
tlhelp32.h 不包含 windows.h 本身是有原因的吗?我一直在与大量的编译器错误作斗争,因为我在包含 tlhelp32.h 之后包含了 windows.h。这是设计决定还是出于什么原因?
我是一名优秀的程序员,十分优秀!