不太明白 golang 官方设计 slice 这种数据结构的初衷在哪?

2019-07-09 21:48:39 +08:00
 Buffer2Disk

不太明白 golang 官方设计 slice 这种可变长数据结构的初衷在哪?是速度更快么还是?

为什么不能跟其他语言一样设计的易用一点呢,有没有大佬出来解惑一下的

感觉这个数据结构用起来要非常的小心,如果按照其他语言的模式来思考,就会产生意想不到的结果

比如下面这 2 个案例

https://v2ex.com/t/581264

https://www.zhihu.com/question/27161493

6007 次点击
所在节点    Go 编程语言
29 条回复
trait
2019-07-09 23:58:16 +08:00
就是设计的不合理
BOYPT
2019-07-10 00:08:17 +08:00
一些 trade off 吧,也没哪里不易用啊,理解这个模型即可,常见用法都是 s = append(s, item), 旧的 s 不再使用
Vegetable
2019-07-10 00:09:44 +08:00
善用指针和 copy。
reus
2019-07-10 00:10:02 +08:00
https://blog.golang.org/go-slices-usage-and-internals

另外,C++ 的 std::vector 也是差不多的结构
sunny352787
2019-07-10 00:24:26 +08:00
你把 golang 当 C 用就明白了
jinliming2
2019-07-10 00:33:26 +08:00
好像一个是数组,一个是切片,数组长度是不能变的,声明多少就是多少,切片是对一个数组中一部分的引用。
写 C++ 的时候就有过这样的情况,你需要一个数组的话,就要在代码里写死长度,或是通过 new 来分配一个固定长度的数组,总之数组一旦创建,长度就不可变,如果容量不够的话,就要重新分配一个数组,然后把旧数据复制过去,然后把旧数组释放掉(代码里写死的长度的数组就不能扩展了)。
Go 其实也是一样的,数组一旦创建长度就不能变,因为向系统申请的连续内存空间已经确定了,后面可能已经存了其他数据,不可以直接越界。
而 Go 为了方便,提供了一个切片(语法上,数组是中括号里要写固定长度,而切片就直接是一对中括号),切片实际上就是个指针,底层需要一个数组来作为存储空间,切片的起始位置一定是在数组头(也可以往后移动,只要不超出数组长度范围就行,但是往后移动了就移不回来了,相当于少了一个存储空间),切片的长度一定小于等于数组长度。以此来提供灵活的数组访问。
在 append 的时候就会出现这样的问题,如果容量不够了,就和 C++ 一样,需要重新创建一个数组,把数据复制过去,只不过这个过程被自动化了,新数组容量我印象中是以两倍的方式来增长的。

其实我觉得如果你知道它的原理,再稍微知道一些 C++ 的东西,就觉得其实也没啥不合理的,知道了原理之后就不会出错了,而且还觉得相比 C++ 还挺好用的。
cest
2019-07-10 00:44:10 +08:00
你的其他语言不会都是些类 script 语言吧?
lynskylate
2019-07-10 00:51:59 +08:00
@jinliming2 #5 对比也应该用 vector 来对比吧,看似提供了数组的语法糖却容易让人产生混乱
nethard
2019-07-10 01:31:05 +08:00
切片的设计初衷应该是提供一种轻量级的基础数据结构作为语言特性,Go 对于其他重型数据结构的支持则有所欠缺,当然只是做 CRUD 的话也用不到什么太重型的。
yegle
2019-07-10 02:23:01 +08:00
nullprogram.com/blog/2019/06/30/ 看这个可能方便理解
bobuick
2019-07-10 06:39:40 +08:00
哪个高级点的语言不需要一个可变长的数组? 用 cpp 你不用 vector 么,写死自己要
xiadong1994
2019-07-10 06:53:31 +08:00
@reus C++的 vector 在按值传递的时候底层数组也会复制一遍,跟 Go 这种虽然是按值传递但是却是一层 shallow copy 的行为还是不太一样吧
kidlj
2019-07-10 07:10:15 +08:00
Ken Thompson 设计的哟。
ericgui
2019-07-10 08:58:48 +08:00
其实可变长度的数组是 ok 的,但能不能叫做 DynamicArray 之类的名字,其他语言的程序员也能看得懂嘛。叫 slice 简直不能太傻了
myyou
2019-07-10 10:09:50 +08:00
@ericgui 实际叫切片并没有什么问题,slice 底层实现的确是取数组的一个切片。而按照 c 语言的的动态数组来看,一旦确定长度,并不能更改,所以叫 DynamicArray 并不准确。
cokyhe
2019-07-10 10:33:49 +08:00
官方为了切 jj 用的
ThanksSirAlex
2019-07-10 11:06:29 +08:00
因为数组长度被设计成了不可变的,所以需要一个更灵活的结构,就像 java C#里面的 string 和 stringbuilder
tiedan
2019-07-10 11:11:04 +08:00
Golang 还有 nil != nil 呢
skadi
2019-07-10 11:16:05 +08:00
std::vector
ensonmj
2019-07-10 12:25:30 +08:00
对比下 rust 的 slice,就会觉得 go 的还不错了。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/581486

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX