一个初始化 slice 的问题

2023-06-06 23:07:54 +08:00
 ben548
问一个初始化 slice 的问题,
之前初学 golang 的时候,我经常用下面这种方式来使用 slice:
source := []int{1,2,3,4,5}
res := make([]int, 0)
for _,v := range source {
res = append(res, v)
}
后来了解了 slice 的相关源码之后,发现上面这种写法会导致 slice 多次扩容,便将代码优化成了这种:
source := []int{1,2,3,4,5}
res := make([]int, len(source))
for k,v := range source {
res[k] = v
}
但是遇到一个问题,就是有的时候 source 里面的内容不是我想要的,需要对 v 或者 k 做判断再赋值,如果不符合要求就 continue ,用上面这种方案就会导致 res 部分 index 下是默认的空值 0 。
发现这一情况之后,又改成了下面这种形式:
source := []int{1,2,3,4,5}
res := make([]int, 0, len(source))
for k,v := range source {
if condition {
res = append(res, v)
}
}
因为初始化的时候设置了 cap 字段,这种方案不会像第一个方案那样发生扩容,目前是我想到的最优解了,我想问这种场景下这种 slice 的初始化是最优方案了吗?
1209 次点击
所在节点    Go 编程语言
8 条回复
rrfeng
2023-06-07 00:15:17 +08:00
看起来最后一种没啥毛病了。
另外这点开销大部分情况下你都不用关心…
ben548
2023-06-07 00:33:03 +08:00
@rrfeng 确实是这样,性能影响非常有限,我也是自己去思考,总结一下,这玩意面试的时候有的时候爱问,思考完理解透了面试就不慌
GopherDaily
2023-06-07 00:36:52 +08:00
Ericcccccccc
2023-06-07 01:09:10 +08:00
一般就是你最后那种写法.
matrix1010
2023-06-07 10:04:56 +08:00
没有银弹。假如你的 source 有 100 万个元素但过滤完只有 10 个指定 capacity 就比较浪费了。或者如果 source 没有用你甚至可以直接写回 source 里不用 make 一个新 slice
sunznx
2023-06-07 10:18:26 +08:00
先瞎 j8 写,有性能问题再改,花里胡哨,什么网站的流量需要考虑这些鬼东西
CLMan
2023-06-07 12:16:28 +08:00
如果能预估最大容量,就是第 3 种写法。

go 的 slice 和 java 的 ArrayList 差不多,就是我们在数据结构与算法里面学到的基于数组实现的列表,基本的扩容策略是双倍扩容:每次 cap*2 ,摊还每次插入 O(1)。

所以第三种写法是在使用数组实现的列表时的常识,与具体语言无关。
hzzhzzdogee
2023-06-11 22:03:05 +08:00
纯复制的时候我喜欢直接

`copy()`

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

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

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

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

© 2021 V2EX