V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ben548
V2EX  ›  Go 编程语言

一个初始化 slice 的问题

  •  
  •   ben548 · 2023-06-06 23:07:54 +08:00 via Android · 1195 次点击
    这是一个创建于 540 天前的主题,其中的信息可能已经有所发展或是发生改变。
    问一个初始化 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 的初始化是最优方案了吗?
    8 条回复    2023-06-11 22:03:05 +08:00
    rrfeng
        1
    rrfeng  
       2023-06-07 00:15:17 +08:00 via Android
    看起来最后一种没啥毛病了。
    另外这点开销大部分情况下你都不用关心…
    ben548
        2
    ben548  
    OP
       2023-06-07 00:33:03 +08:00 via Android
    @rrfeng 确实是这样,性能影响非常有限,我也是自己去思考,总结一下,这玩意面试的时候有的时候爱问,思考完理解透了面试就不慌
    GopherDaily
        3
    GopherDaily  
       2023-06-07 00:36:52 +08:00
    Ericcccccccc
        4
    Ericcccccccc  
       2023-06-07 01:09:10 +08:00
    一般就是你最后那种写法.
    matrix1010
        5
    matrix1010  
       2023-06-07 10:04:56 +08:00
    没有银弹。假如你的 source 有 100 万个元素但过滤完只有 10 个指定 capacity 就比较浪费了。或者如果 source 没有用你甚至可以直接写回 source 里不用 make 一个新 slice
    sunznx
        6
    sunznx  
       2023-06-07 10:18:26 +08:00
    先瞎 j8 写,有性能问题再改,花里胡哨,什么网站的流量需要考虑这些鬼东西
    CLMan
        7
    CLMan  
       2023-06-07 12:16:28 +08:00
    如果能预估最大容量,就是第 3 种写法。

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

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

    `copy()`
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1032 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:01 · PVG 05:01 · LAX 13:01 · JFK 16:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.