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

golang 有 array 为啥要 slice

  •  
  •   GGGG430 · 2022-02-13 18:46:25 +08:00 · 3182 次点击
    这是一个创建于 802 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    14 条回复    2022-02-14 10:54:28 +08:00
    Mitt
        1
    Mitt  
       2022-02-13 18:59:44 +08:00 via iPhone
    定长数组和变长数组的行为也不一样 不可互相替代的
    cmdOptionKana
        2
    cmdOptionKana  
       2022-02-13 19:48:58 +08:00
    slice 底层就是用 array 实现的,只是包裹了很薄的一层而已,目的就是为了更方便地使用 array 。

    换个角度讲,假设官方没有提供 slice ,你自己也必然会做一个类似的东西出来。由于可以预料几乎每个人在使用 array 时都会包裹一层,加些自动变长的方法,那官方直接提供一个类型就很合理了。
    Hanggi
        3
    Hanggi  
       2022-02-13 20:20:35 +08:00   ❤️ 1
    https://go.dev/tour/moretypes/8

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

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

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

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

    Go 语言教程做的还是很不错的,有空可以多看看。
    billzhuang
        4
    billzhuang  
       2022-02-13 21:00:56 +08:00 via iPhone
    我记得 rust 也是类似的原因
    fengjianxinghun
        5
    fengjianxinghun  
       2022-02-13 21:10:07 +08:00   ❤️ 1
    @cmdOptionKana 想多了,先前没有泛型你是包裹不出一个类型安全的 slice 的,官方的 slice 是编译器开后门。
    Building
        6
    Building  
       2022-02-13 21:11:34 +08:00 via iPhone
    难道不是为了实现 Array 的 cow 机制吗?
    Yother
        7
    Yother  
       2022-02-13 21:11:42 +08:00 via Android
    为了性能。
    ThanksSirAlex
        8
    ThanksSirAlex  
       2022-02-13 21:22:30 +08:00
    就是包装了一个可变长度的数组,实际运用中固定长度的数组可用性太差
    BeautifulSoap
        9
    BeautifulSoap  
       2022-02-13 21:51:14 +08:00   ❤️ 1
    就是为了可变长度啊,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
    yulon
        10
    yulon  
       2022-02-13 21:55:32 +08:00
    @BeautifulSoap 准确来说是 span ,vector 没有办法引用 array ,只是 Go 有 GC 所以可以延长生命周期
    jim9606
        11
    jim9606  
       2022-02-13 22:00:18 +08:00
    对于只读或进行原地修改的数组参数的 func ,使用 slice 可以免去需要传三个参数(*arr,pos,len)的麻烦。
    golang 中 array 的长度是类型的一部分,对于希望接收不定长函数的 func ,只能用 slice 。
    laravel
        12
    laravel  
       2022-02-14 04:28:39 +08:00
    dynamic array
    fgwmlhdkkkw
        13
    fgwmlhdkkkw  
       2022-02-14 10:33:39 +08:00
    你不用不就完事了……
    GGGG430
        14
    GGGG430  
    OP
       2022-02-14 10:54:28 +08:00
    @BeautifulSoap #9 感谢回答, 只有你的回答靠谱点; 不过还是要纠正一下最后的扩容策略, 有三种可能, 即 doublecap, newcap, 1.25 倍循环三种, 最后还会内存对齐
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3610 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:22 · PVG 12:22 · LAX 21:22 · JFK 00:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.