Golang Go语言中有了array为啥还要有slice

Golang Go语言中有了array为啥还要有slice

如题, slice 相比于 array 的优势是什么, 平时还真没想过, 网上搜了一下, 感觉是长度可变这个优势 ? 各位大佬有了解的吗

15 回复

定长数组和变长数组的行为也不一样 不可互相替代的

更多关于Golang Go语言中有了array为啥还要有slice的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


slice 底层就是用 array 实现的,只是包裹了很薄的一层而已,目的就是为了更方便地使用 array 。

换个角度讲,假设官方没有提供 slice ,你自己也必然会做一个类似的东西出来。由于可以预料几乎每个人在使用 array 时都会包裹一层,加些自动变长的方法,那官方直接提供一个类型就很合理了。

https://go.dev/tour/moretypes/8

看一下官方教程就可以知道,Slice 并不会存储任何数据。而是指向他底层的一个 array ,当你修改 slice 的数据实际上是在修改底层的 array 。

还有就是可以发现 Go 语言中没有 push 反而用 append 来添加元素。

https://go.dev/tour/moretypes/15

官方教程中也涉及到了,如果你增加元素到超过了底层的 array 的长度,他就会给你重新分配一个新的 array 来满足需求。

Go 语言教程做的还是很不错的,有空可以多看看。

我记得 rust 也是类似的原因

想多了,先前没有泛型你是包裹不出一个类型安全的 slice 的,官方的 slice 是编译器开后门。

难道不是为了实现 Array 的 cow 机制吗?

为了性能。

就是包装了一个可变长度的数组,实际运用中固定长度的数组可用性太差

就是为了可变长度啊,array 的长度是固定且不可变的,你创建 array 的时候必须明确指定这个 array 的长度,而实际开发时是很难预先知道要存入的数据到底多长的。难道为了能预留够长度直接创建个需求中可能来的最大长度(比如 32768 之类的)的数组吗(当然,在 c 语言中这是基操,勿惊)

还有,golang 的 slice 实际上就是对等于 c++中的 vector ,两者原理是一模一样的都是基于 array 的抽象数据结构

lz 看了上面官方的说明之后如果有兴趣继续了解的话,可以来看邓俊辉老师的《数据结构》公开课,第二章的向量就是讲的 c++的 vector ,和 go 的 slice 是完全相通的,甚至里面还详细告诉你为什么每次 go 的 slice 的扩容策略是 cap 翻倍之类的

https://www.xuetangx.com/course/THU08091000384/1391601

准确来说是 span ,vector 没有办法引用 array ,只是 Go 有 GC 所以可以延长生命周期

对于只读或进行原地修改的数组参数的 func ,使用 slice 可以免去需要传三个参数(*arr,pos,len)的麻烦。
golang 中 array 的长度是类型的一部分,对于希望接收不定长函数的 func ,只能用 slice 。

dynamic array

你不用不就完事了……

#9 感谢回答, 只有你的回答靠谱点; 不过还是要纠正一下最后的扩容策略, 有三种可能, 即 doublecap, newcap, 1.25 倍循环三种, 最后还会内存对齐

在Go语言中,虽然array(数组)和slice(切片)都用于存储一系列的元素,但它们在设计初衷和使用场景上有显著的区别,这也是为什么Go语言在引入array之后还需要slice的原因。

array的长度是固定的,在声明时就必须确定其大小,且之后无法改变。这种特性使得array在处理固定大小的数据集时非常高效,但缺乏灵活性。

相比之下,slice是对array的一个抽象和封装,它提供了更为灵活和强大的动态数组功能。slice具有三个关键属性:指向数组的指针、长度和容量。这使得slice可以动态地增长和缩小,而无需像array那样在声明时就确定大小。此外,slice的底层实现是共享数组的内存,这大大提高了内存利用率和性能。

slice还支持更为丰富的操作,如切片、追加元素、复制等,这些操作在array上实现起来会更为复杂和低效。

因此,arrayslice在Go语言中各有其独特的用途。array适用于需要固定大小的数据集,而slice则更适合需要动态调整大小的数据集。这种设计使得Go语言在提供高效内存管理的同时,也保持了代码的灵活性和可读性。所以,Go语言在有了array之后,还需要slice来满足更广泛的编程需求。

回到顶部