当前位置:首页 > 科技  > 软件

Go 面试中的隐藏陷阱:SliceHeader 问题解析

来源: 责编: 时间:2024-06-12 17:31:35 279观看
导读大家好,我是煎鱼。最近也是面试季+毕业季了,很多同学正在积极准备面试。尤其是很多同学,已经通过官网资料熟悉了 Go 基本语法,但没有太大把握。希望对一些常见的棘手面试问题做一些预习。今天和大家学习 @Harutyun Mardir

大家好,我是煎鱼。WpK28资讯网——每日最新资讯28at.com

最近也是面试季+毕业季了,很多同学正在积极准备面试。尤其是很多同学,已经通过官网资料熟悉了 Go 基本语法,但没有太大把握。希望对一些常见的棘手面试问题做一些预习。WpK28资讯网——每日最新资讯28at.com

今天和大家学习 @Harutyun Mardirossian 大佬分享的面试题,一起进步!WpK28资讯网——每日最新资讯28at.com

面试问题

请先在脑子里思考一下具体的运行结果,再查看答案。WpK28资讯网——每日最新资讯28at.com

如下代码:WpK28资讯网——每日最新资讯28at.com

func main() {    s := make([]int, 0, 2)    doSomething(s)    fmt.Println(s)}func doSomething(a []int) {    a = append(a, 1)}

面试问题:fmt.Println 的输出结果是什么?WpK28资讯网——每日最新资讯28at.com

问题解析

运行程序,查看输出结果:WpK28资讯网——每日最新资讯28at.com

[]

fmt.Println 最终打印的是一个长度为 0 的切片。WpK28资讯网——每日最新资讯28at.com

答案是:空切片。(你答对了吗?)WpK28资讯网——每日最新资讯28at.com

在 Go 中,函数参数是按值传递的,这意味着上述代码在参数传递时,创建了参数值的副本并传递给函数。WpK28资讯网——每日最新资讯28at.com

而切片实际上是一个包含长度(len)、容量(cap)和指向底层数组指针(data)的结构体。WpK28资讯网——每日最新资讯28at.com

当我们将切片作为函数参数传递时,实质上复制的是切片的 SliceHeader,对应的底层数组是保持不变的。WpK28资讯网——每日最新资讯28at.com

结合代码来讲,就是因为在 doSomething 函数中,创建了 SliceHeader 的新副本。然后 append 函数会在超过容量时重新分配新切片,并返回更新后的切片。WpK28资讯网——每日最新资讯28at.com

深入验证

我们可以使用 unsafe 包去打印 SliceHeader(切片头),进行进一步的验证和分析。WpK28资讯网——每日最新资讯28at.com

如下代码:WpK28资讯网——每日最新资讯28at.com

type SliceHeader struct {    Data uintptr    Len  int    Cap  int}func main() {    s := make([]int, 0, 2)    sh := (*SliceHeader)(unsafe.Pointer(&s))    fmt.Println(sh)    doSomething(s)}func doSomething(a []int) {    a = append(a, 1)    sh := (*SliceHeader)(unsafe.Pointer(&a))    fmt.Println(sh)}

输出结果:WpK28资讯网——每日最新资讯28at.com

&{1374389592336 0 2} // main&{1374389592336 1 2} // doSomething

两个切片的 Data 指针地址指向的是同一个底层数组。但由于长度不同,它们在应用的表现上是两个不同的切片。WpK28资讯网——每日最新资讯28at.com

这也印证了前面问题的结果是输出了空切片,切片长度为 0 的内部原理。WpK28资讯网——每日最新资讯28at.com

变通方法

这种情况下,建议是修改写法,提高代码易读性。否则后续维护也比较麻烦,不熟悉的同学咋一眼一看很有可能发现不了问题。WpK28资讯网——每日最新资讯28at.com

但如果你还是希望输出你想要的切片值,可以采取以下变通方法。WpK28资讯网——每日最新资讯28at.com

改动后的代码:WpK28资讯网——每日最新资讯28at.com

func main() {    s := make([]int, 0, 2)    doSomething(s)    fmt.Println(s[:1]) // 进行新的切片操作}func doSomething(a []int) {    a = append(a, 1)}

输出结果:WpK28资讯网——每日最新资讯28at.com

[1]

原因是在进行 s[:1] 切片操作时,本质上是创建了一个新的 SliceHeader,所以可以正常打印和获取预期的元素。WpK28资讯网——每日最新资讯28at.com

当然,还有一种常见的写法就是切片 append 等变更后一定做一遍再赋值,这样可以规避掉不少使用上的细节坑。WpK28资讯网——每日最新资讯28at.com

总结

今天这篇文章讨论了一个很常见的 Go 面试问题,内容涉及切片作为函数参数的传递和修改。WpK28资讯网——每日最新资讯28at.com

重点在于切片作为参数是按值传递的,因此函数内部的修改不会影响外部变量。WpK28资讯网——每日最新资讯28at.com

如果仍然希望获取可以通过切片操作,重新切分一下新的切片结果集就可以了。WpK28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-93368-0.htmlGo 面试中的隐藏陷阱:SliceHeader 问题解析

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C#托管堆遭破坏问题溯源分析

下一篇: 基于 Spring Boot 与 WebSocket 实现实时车位管理与状态更新

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 掘力计划第 20 期:Flutter 混合开发的混乱之治

    在掘力计划系列活动第20场,《Flutter 开发实战详解》作者,掘金优秀作者,Github GSY 系列目负责人恋猫的小郭分享了Flutter 混合开发的混乱之治。Flutter 基于自研的 Skia 引擎
  • 三万字盘点 Spring 九大核心基础功能

    大家好,我是三友~~今天来跟大家聊一聊Spring的9大核心基础功能。话不多说,先上目录:图片友情提示,本文过长,建议收藏,嘿嘿嘿!一、资源管理资源管理是Spring的一个核心的基础功能,不
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    来源:征探财经作者:陈香羽随着流量红利的退潮,电商的存量博弈越来越明显。曾经主攻中高端与品质的淘宝天猫、京东重拾“低价”口号。而过去与他们错位竞争的拼多多,靠
  • 三星推出Galaxy Tab S9系列平板电脑以及Galaxy Watch6系列智能手表

    2023年7月26日,三星电子正式发布了Galaxy Z Flip5与Galaxy Z Fold5。除此之外,Galaxy Tab S9系列平板电脑以及三星Galaxy Watch6系列智能手表也同期
  • Android 14发布:首批适配机型公布

    5月11日消息,谷歌在今天凌晨举行了I/O大会,本次发布会谷歌带来了自家的AI语言模型PaLM 2、谷歌Pixel Fold折叠屏、谷歌Pixel 7a手机,同时发布了Androi
  • 联想小新Pad Pro 12.6将要推出,搭载高通骁龙 870 处理器

    联想小新Pad Pro 12.6将于秋季新品会上推出,官方按照惯例直接在发布会前给出了机型的所有参数。联想小新 Pad Pro 12.6 将搭载高通骁龙 870 处理器,重量为 5
Top