总结golang slice一些需要注意的知识

slice拷贝冒号和copy区别

冒号位浅拷贝,只会复制slice结构,不会复制指向的数组数据;copy为深拷贝,仅会复制slice结构,还会复制数组数据。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
nums := []int{2, 1, 1}
nums2 := nums[:]
nums3 := dump(nums)
nums[0] = 1 //会影响nums2但不会影响num3


//深拷贝
func dump(a []int) []int {
	b := make([]int, len(a))
	copy(b, a)
	return b
}

capacity vs length

The length is the number of elements referred to by the slice. The capacity is the number of elements in the underlying array

capacity才是真正的slice长度!length只是用户可引用的个数

The slice type is an abstraction built on top of Go’s array type. A slice is a descriptor of an array segment.

slice底层其实就是一个数组,这跟java的ArrayList有点像

1
2
3
4
q1 := make([]int, 1, 10)
q2 := make([]int, 1)  
fmt.Printf("q1  length=%d  capacity=%d\n", len(q1), len(q2)) 
fmt.Printf("q2  length=%d capacity=%d\n", len(q2), cap(q2))

Running result:

1
2
q1  length=1  capacity=10
q2  length=1 capacity=1

调用make slice不指定capacity时,slice像一个数组,capacity和lenght相等

len和cap允许传入nil,传入nil表示长度为0

冒号取部分以capaticy为界

1
2
3
4
q1 := make([]int, 1, 10) //建立时,被引用的元素个数为1
q[1] // index out of range
q1 = q1[:3] //slice的底层数组不变,改变了引用的元素个数为3
q[1] // normal

Array简介

golang的一个Array类型不仅由element type决定,而且由length决定。比如 [4]int 和 [5]int 是两个不同的type。

Array是值,跟int、float等普通类型相似,是一个整体,并不是指向第一个元素地址的指针。传入函数时会,默认传的是值,即传的是值的copy。例如:

1
2
3
4
5
6
7
8
func main() {
	q := [2]int{}
	foo(q)
}
func foo(arr [2]int) {
	arr[0] = 99
}

调用foo函数后,q并不会有任何变化。

Go’s arrays are values. An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents. (To avoid the copy you could pass a pointer to the array, but then that’s a pointer to an array, not an array.) One way to think about arrays is as a sort of struct but with indexed rather than named fields: a fixed-size composite value.

切片截取

只是改变slice数据结构,不会改变数组数据。当然slice append,可能会导致数组数据的内存空间的重新分配

1
2
3
4
5
a := []int{1, 2, 3}
a = a[:1]
fmt.Println(a)
a = a[:3]
fmt.Println(a) //依然是[1,2,3]

参考

https://blog.golang.org/slices-intro