cover_image

Go:数组与切片的区别

leizongmin 该账号已冻结
2020年03月14日 06:56

假设如下代码:

func f() {
x, y := make([]byte, 9000), make([]byte, 9)
a := x
b := y
// ...
}

大多数人按照“直观”的理解可能会觉得执行 a := x  会比 b := y  代价更高,因为切片 x  比 y  大得多。其实 x  和 y  的数据类型都是  []byte ,在 Go 内部每个切片实际存储的数据是三个 uintptr  的长度,所以对 a  和 b  的赋值需要的代价是一样的,与切片数据的实际长度无关。

需要特别说明的是,在 Go 语言中有两种看起来很像的数据类型:数组(array)和切片(slice)。


数组

数组的长度是固定的,比如 [4]int{}  表示一个长度为 4 的 int  数组,其在内存中的数据结构是这样的:

图片
数据的数据结构(来源:The Go Blog)

当将数组赋值给一个变量,实际上会将数组的整块内存区域都复制一份。


切片

切片的长度是不固定的,可以随使用需要动态增长,通过 []int{}  表示一个 int  切片,其在内存中的数据结构是这样的:

图片
切片的数据结构(来源:The Go Blog

第一部分是切片对应的数组指针(ptr),第二部分是切片的长度(len),第三部分是切片的容量(cap)(即所指向的数组的实际长度)。当将切片复制给一个变量,实际上是将切片的 ptr、len、cap 这三项数据复制一份,而数据指向的数组还是原来那个。所以此时修改了切片某个索引位置的数据时,会影响到所有相同 ptr 的切片。


参考链接

  • Are large slices more expensive than smaller ones?[1] , Dave Cheney
  • Go Slices: usage and internals[2], The Go Blog

参考资料

[1]

Are large slices more expensive than smaller ones?: https://dave.cheney.net/2020/03/01/are-large-slices-more-expensive-than-smaller-ones

[2]

Go Slices: usage and internals: https://blog.golang.org/go-slices-usage-and-internals


继续滑动看下一个
该账号已冻结
向上滑动看下一个