Golang Go语言中为什么很少使用数组?
大家好,我是 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]
阅读上面这段代码,我们使用三种方式声明数组,其中 arr1
和 arr2
的区别是,arr1
在声明时没有为数组赋值,所以输出结果是类型零值 [0 0]
。
需要注意的是,arr3
没有指定数组的长度,而是使用 [...]
替代,这实际上是 Go 语言中声明数组的语法糖,编译时通过数组的赋值,自动推断数组的长度,我们可以使用内置函数 len()
查询数组的长度。
数组的特性
在了解嘞数组的声明方式之后,我们再来介绍一下数组具有哪些特性。
数组的长度和类型共同决定数组的类型,例如 var arr1 [2]int
和 var 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 项目开发中很少使用的原因。
主要原因有两点,一是数组不可以扩容;二是值传递,大数组要特别小心,如果无法避免使用大数组,可以使用数组指针。
Golang Go语言中为什么很少使用数组?
更多关于Golang Go语言中为什么很少使用数组?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
可以认为 slice 是 array 的门面和装饰器?
可以认为 slice 是一个 指向 array 的 fat-pointer
数组值传递也是只传递指针吧
我们组是严禁使用数组, 但凡代码里发现有数组, 就没法合进去.
我不同意。只要能静态长度肯定用 array 啊
go 不知道, java 反正是没见谁用…
数组是定长的,其实更像 Python 里的 tuple ,只是元素必须同类型。
切片是可变数组,你想想哪个语言里真的会用很多定长数组的???
去看看网络协议开发的,数组无处不在, 网络协议封装那就是数组干的活, 不使用数组一看就是不专业的。 好处显而易见, 省空间,性能更好, 使用 [:] 复制为切片也很方便, 居然在项目里禁用数组,这规定也太奇葩了吧。
这就跟阿里云的 java 军规一个道理。先对齐颗粒度,打通底层逻辑。完全的无厘头限制。
你们的代码规范疑似有点魔怔了
要看使用场景,只是在大多数场景中适用。
在Go语言中,数组的使用确实不如切片(slice)频繁,这主要有以下几个专业原因:
-
固定长度:数组在声明时其长度是固定的,这意味着一旦数组被创建,其大小就不能改变。这种特性在很多动态数据处理的场景中显得不够灵活。
-
内存复制:由于数组是值类型,当数组作为函数参数传递或赋值给另一个变量时,会进行整个数组的复制。对于大型数组,这种复制操作会导致性能下降和内存浪费。
-
切片优势:切片是对数组的一个抽象和封装,提供了更灵活的长度管理和更高效的内存使用。切片是基于底层数组的,但可以动态增长和缩小,且切片间的操作通常只涉及指针和长度的修改,避免了大量的数据复制。
-
接口兼容性:Go语言中的很多标准库函数和接口都是基于切片设计的,而不是数组。这使得使用切片能更方便地利用这些库函数和接口。
-
代码可读性:切片更符合现代编程的惯用方式,其动态性和灵活性使得代码更加简洁和易读。
综上所述,虽然数组在Go语言中仍然有其应用场景(如需要固定大小且高性能的场景),但切片因其灵活性和高效性,在大多数情况下成为了更好的选择。因此,在Go语言中,切片的使用更为广泛,而数组则相对较少使用。