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

Go 语言为什么很少使用数组?

  •  
  •   frankphper · 118 天前 · 3400 次点击
    这是一个创建于 118 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家好,我是 frank ,「 Golang 语言开发栈」公众号作者。

    01 介绍

    在 Go 语言中,数组是一块连续的内存,数组不可以扩容,数组在作为参数传递时,属于值传递。

    数组的长度和类型共同决定数组的类型,不同类型的数组之间不可以比较,否则在编译时会报错。

    因为数组的一些特性,我们在 Go 项目开发中,很少使用数组。本文我们介绍一下数组的特性。

    02 数组

    声明方式

    在 Go 语言中,数组的声明方式有三种。

    示例代码:

    func main() {
    	var arr1 [2]int
    	var arr2 = [2]int{1, 2}
    	var arr3 = [...]int{1, 2}
    	fmt.Println(arr1)
    	fmt.Println(arr2)
    	fmt.Println(arr3)
    }
    

    输出结果:

    [0 0]
    [1 2]
    [1 2]
    

    阅读上面这段代码,我们使用三种方式声明数组,其中 arr1arr2 的区别是,arr1 在声明时没有为数组赋值,所以输出结果是类型零值 [0 0]

    需要注意的是,arr3 没有指定数组的长度,而是使用 [...] 替代,这实际上是 Go 语言中声明数组的语法糖,编译时通过数组的赋值,自动推断数组的长度,我们可以使用内置函数 len() 查询数组的长度。

    数组的特性

    在了解嘞数组的声明方式之后,我们再来介绍一下数组具有哪些特性。

    数组的长度和类型共同决定数组的类型,例如 var arr1 [2]intvar arr2 [3]int 是不同的类型。并且不同类型的数组之间是不可以比较的,数组也不可以扩容。

    如果数组长度小于等于 4 时,在编译时会对数组做内存优化,程序启动时在栈区初始化数组,我们在使用数组类型时,也可以注意一下这一点。

    使用数组下标访问数组中的元素时,越界访问,在编译时会报错。但是,如果我们使用变量 arr[i] 作为数组下标访问数组中的元素,在编译时无法检查是否越界访问,在运行时会引发 panic

    示例代码:

    func Store() {
    	var arr [2]int
    	for i := 0; i < 5; i++ {
    		arr[i] = i + 1
    	}
    	fmt.Println(arr)
    }
    

    输出结果:

    panic: runtime error: index out of range [2] with length 2
    
    goroutine 1 [running]:
    ...
    

    在作为参数传递数组类型的变量时,都属于值传递,我们在使用数组类型的参数时,要特别注意。

    示例代码:

    func main() {
    	var arr2 = [2]int{1, 2}
    	Get(arr2)
    	fmt.Printf("arr2=%p\n%d\n", &arr2, arr2)
    }
    
    func Get(arr [2]int) {
    	fmt.Printf("Get()=%p\n%d\n", &arr, arr)
    }
    

    输出结果:

    Get()=0xc0000120f0
    [1 2]
    arr2=0xc0000120b0
    [1 2]
    

    阅读上面这段代码,我们可以发现数组在作为参数传递时,地址发生变化,可以证明其属于值传递,即分配一块新内存,将数组的值拷贝到新内存。

    03 总结

    本文我们通过介绍 Go 语言中数组的一些特性,佐证数组在 Go 项目开发中很少使用的原因。

    主要原因有两点,一是数组不可以扩容;二是值传递,大数组要特别小心,如果无法避免使用大数组,可以使用数组指针。

    12 条回复    2024-01-06 14:09:27 +08:00
    herozzm
        1
    herozzm  
       118 天前
    结论就不同意,我用的挺多的
    arloor
        2
    arloor  
       118 天前 via Android
    可以认为 slice 是 array 的门面和装饰器?
    thevita
        3
    thevita  
       118 天前
    可以认为 slice 是一个 指向 array 的 fat-pointer
    ninjashixuan
        4
    ninjashixuan  
       118 天前
    数组值传递也是只传递指针吧
    bthulu
        5
    bthulu  
       118 天前
    我们组是严禁使用数组, 但凡代码里发现有数组, 就没法合进去.
    deorth
        6
    deorth  
       118 天前 via Android
    我不同意。只要能静态长度肯定用 array 啊
    qiany
        7
    qiany  
       118 天前
    go 不知道, java 反正是没见谁用...
    rrfeng
        8
    rrfeng  
       118 天前 via Android
    数组是定长的,其实更像 Python 里的 tuple ,只是元素必须同类型。
    切片是可变数组,你想想哪个语言里真的会用很多定长数组的???
    prenwang
        9
    prenwang  
       118 天前
    去看看网络协议开发的,数组无处不在, 网络协议封装那就是数组干的活, 不使用数组一看就是不专业的。 好处显而易见, 省空间,性能更好, 使用 [:] 复制为切片也很方便, 居然在项目里禁用数组,这规定也太奇葩了吧。
    sampeng
        10
    sampeng  
       117 天前
    @prenwang 这就跟阿里云的 java 军规一个道理。先对齐颗粒度,打通底层逻辑。完全的无厘头限制。
    xuyang2
        11
    xuyang2  
       116 天前
    @bthulu 你们的代码规范疑似有点魔怔了
    frankphper
        12
    frankphper  
    OP
       112 天前
    @prenwang 要看使用场景,只是在大多数场景中适用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1176 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:57 · PVG 01:57 · LAX 10:57 · JFK 13:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.