Go语言切片扩充

Go语言的切片(slice)和其他语言一样,有上界和下界,且切片包含上界不包含下界:

var a [10]int
fmt.Println(a[0:10])
fmt.Println(a[:10])
fmt.Println(a[0:])
fmt.Println(a[:])

以上四个输出都一样。

且切片在Go语言中是数组(array)的引用,即修改切片中的元素会影响数组原本的对应元素,并且进一步影响到该数组的其他切片:

func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)

	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b)

	b[0] = "XXX"
	fmt.Println(a, b)
	fmt.Println(names)
}

输出是:

[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]

切片有长度(length)和容量(capacity)两个属性,可用len(s)cap(s)获取。

长度就是切片元素个数,但是容量是从切片的第一个元素到其原数组最后一个元素的元素个数。

也就是说,切片的上界变了之后,切片的容量变了,但下界变动不会对容量造成影响。

而访问切片内元素或者对切片进行切片,下标是否越界是看该切片的容量的。只要下标在0~容量-1的范围内,就不会越界。可以看下面这个例子:

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	s = s[:0]
	printSlice(s)
	
	s = s[:4]
	printSlice(s)

	s = s[2:]
	printSlice(s)
	
	s = s[1:4]
	printSlice(s)

	s = s[2:]
	printSlice(s)
	
	s = s[:4]
	printSlice(s)
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

运行结果如下:

len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
len=3 cap=3 [7 11 13]
len=1 cap=1 [13]
panic: runtime error: slice bounds out of range [:4] with capacity 1

goroutine 1 [running]:
main.main()
	/tmp/sandbox3310609988/prog.go:24 +0xe5