AI不可尽信

news/2024/12/22 2:24:31/

看到某项目有类似这样的一段代码

leaves := make([]int, 10)
leaves = leaves[:0]

没理解这样的连续两行,有何作用? 初始化一个长度和容量都为10的切片,接着把切片长度设置为0

即如下demo: (在线地址)

package mainimport "fmt"func main() {leaves := make([]int, 10)fmt.Println(leaves)leaves = leaves[:0]fmt.Println(leaves)leaves2 := make([]int, 0, 10)fmt.Println(leaves2)
}

输出为:

[0 0 0 0 0 0 0 0 0 0]
[]
[]

为什么不直接leaves := make([]int, 0, 10)? 况且直觉来说,先申请长度为10的,再设置为0, 比直接申请长度为0的,要多一些性能开销吧…

问了下claude.ai

Go语言中leaves := make([]int, 10) leaves = leaves[:0] 和leaves := make([]int, 0, 10) 有何区别?哪种方式更好?

这是一个很好的问题,涉及到 Go 语言中切片的内存分配和使用。让我们详细比较这两种方式:

方式 1:

leaves := make([]int, 10)
leaves = leaves[:0]

方式 2:

leaves := make([]int, 0, 10)

这两种方式的主要区别在于:

  1. 初始化后的状态:

    • 方式 1:初始创建一个长度为 10 的切片,所有元素被初始化为零值(对于 int 类型,就是 0)。然后立即将其长度设置为 0,但保留了容量。
    • 方式 2:创建一个长度为 0,容量为 10 的切片。没有实际的元素被初始化。
  2. 内存分配:

    • 两种方式都会分配能容纳 10 个 int 的底层数组。
  3. 初始化开销:

    • 方式 1:有初始化 10 个元素为零值的开销。
    • 方式 2:没有元素初始化的开销。
  4. 使用方式:

    • 两种方式后续使用 append 的行为是一样的。
  5. 性能:

    • 方式 2 略优于方式 1,因为它避免了不必要的元素初始化。

哪种方式更好?

总的来说,方式 2 leaves := make([]int, 0, 10) 通常被认为是更好的做法,原因如下:

  1. 效率:避免了不必要的元素初始化,特别是当元素类型比 int 更复杂时,这种差异会更明显。

  2. 清晰性:直接表达了"我想要一个空的切片,但预留了 10 个元素的空间"这一意图。

  3. 一致性:与后续使用 append 来添加元素的方式更加一致。

  4. 安全性:避免了可能出现的、使用未被有意义初始化的元素的错误。

示例代码来说明这两种方式的行为:

package mainimport "fmt"func main() {// 方式 1leaves1 := make([]int, 10)fmt.Printf("方式 1 初始: 长度=%d, 容量=%d\n", len(leaves1), cap(leaves1))leaves1 = leaves1[:0]fmt.Printf("方式 1 重置后: 长度=%d, 容量=%d\n", len(leaves1), cap(leaves1))// 方式 2leaves2 := make([]int, 0, 10)fmt.Printf("方式 2: 长度=%d, 容量=%d\n", len(leaves2), cap(leaves2))// 添加元素leaves1 = append(leaves1, 1, 2, 3)leaves2 = append(leaves2, 1, 2, 3)fmt.Printf("方式 1 添加元素后: %v\n", leaves1)fmt.Printf("方式 2 添加元素后: %v\n", leaves2)
}

输出将会是:

方式 1 初始: 长度=10, 容量=10
方式 1 重置后: 长度=0, 容量=10
方式 2: 长度=0, 容量=10
方式 1 添加元素后: [1 2 3]
方式 2 添加元素后: [1 2 3]

这个例子展示了两种方式在实际使用中的相似性,但方式 2 避免了初始的元素初始化步骤。

因此,在大多数情况下,leaves := make([]int, 0, 10) 是更好的选择。



看着Claude.ai的回答,“第一种方式有内存分配”, 于是信心满满提了个pr,结果维护这个项目的丹麦老哥回复:

It literally does the same - it doesn't save any "memory overhead". Sorry. This is too pointless of a change to take.



决定做个性能测试加以佐证。

package mainimport ("testing"
)func BenchmarkMakeWithLength(b *testing.B) {for i := 0; i < b.N; i++ {leaves := make([]int, 10)leaves = leaves[:0]}
}func BenchmarkMakeWithCapacity(b *testing.B) {for i := 0; i < b.N; i++ {leaves := make([]int, 0, 10)_ = leaves}
}

尴尬的是,测试结果,却恰恰并不支持Ai给的这个结论。。


写demo然后查看两者相对应的汇编,好吧,其实两种写法汇编代码是完全一样的。唯一差异也就在于个人习惯和可读性了



http://www.ppmy.cn/news/1534918.html

相关文章

增强现实中的物体识别与跟踪

增强现实&#xff08;AR&#xff09;中的物体识别与跟踪是实现虚拟内容与现实世界无缝融合的关键技术。以下是该领域的主要技术和方法概述&#xff1a; 1. 物体识别 1.1 特征提取 SIFT、SURF、ORB&#xff1a;传统的特征提取算法用于识别图像中的关键点并生成描述符&#xf…

STM32-HAL库驱动DHT11温湿度传感器 --2024.9.28

目录 一、教程简介 二、驱动原理讲解 &#xff08;一&#xff09;通信4步骤 &#xff08;二&#xff09;传感器数据解析 三、CubeMX生成底层代码 &#xff08;一&#xff09;基础配置 &#xff08;二&#xff09;配置DHT11的驱动引脚 &#xff08;三&#xff09;配置串口 四…

选择网络安全模式启动Windows系统,解决PC无法连接网络问题

目录 1、电脑无法连接网络 2、发现C:\Windows\System32\drivers路径下的很多文件不见了 3、使用360安全卫士中的断网急救箱工具修复&#xff0c;也就解决不了问题 4、重启系统&#xff0c;以网络安全模式启动系统&#xff0c;修复系统网络模块&#xff0c;完美解决问题 5、…

Java中的数据格式转换:JSON、XML与Protobuf的应用与选择

Java中的数据格式转换&#xff1a;JSON、XML与Protobuf的应用与选择 大家好&#xff0c;我是微赚淘客返利系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们要聊的主题是Java开发中经常涉及到的一个重要问题——数据格式转换。…

【GEE学习第二期】GEE数据类型、语法

【GEE学习第二期】GEE数据类型、语法 GEE基本数据类型基本语法循环条件判断累加 可视化影像与波段影像集数据导出数值与绘图保存影像 参考 GEE基本数据类型 GEE 中使用的主要数据类型是栅格&#xff0c;涵盖从本地到全球范围的图像&#xff0c;可从数百个卫星和航空资源获得图…

LabVIEW混合控制器质量检测

随着工业自动化水平的提高&#xff0c;对控制器的精度、稳定性、可靠性要求也在不断上升。特别是在工程机械、自动化生产、风力发电等领域&#xff0c;传统的质量检测方法已无法满足现代工业的高要求。因此&#xff0c;开发一套自动化、精确、可扩展的混合控制器质量检测平台成…

【Ubuntu】VMware中虚拟网卡与服务器网卡的绑定

文章目录 服务器网卡和VMware中虚拟网卡的绑定1.在本机上查看需要的网卡名称2.服务器本机设置固定ip3.打开VMware后&#xff0c;将虚拟网卡与本机真实网卡进行绑定。4.给routeOS分配4张网卡&#xff0c;如图所示&#xff1a;5.ubuntu1和ubuntu2只需分配vmnet0和vmnet8即可&…

【HTML5】html5开篇基础(4)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…