2

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

 8 months ago
source link: https://www.v2ex.com/t/1004805
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Go 编程语言

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

  frankphper · 7 小时 37 分钟前 · 1253 次点击

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

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

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

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

声明方式

在 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]

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK