1 切片初始化
1 func printSlice(s []int) {
2 fmt.Printf("len=%d cap=%d underlying array:%p, %v\n", len(s), cap(s), s, s)
3 }
4
5 func sliceInit() {
6
7 var s1 []int //声明s1,并没有初始化,此时s1是nil切片,没有分配底层数组
8 if s1 == nil {
9 fmt.Println("s1 is nil")
10 }
11
12 s2 := []int{}
13 if s2 == nil {
14 fmt.Println("s2 is nil")
15 }
16
17 s3 := make([]int, 0)
18 if s3 == nil {
19 fmt.Println("s3 is nil!")
20 }
21
22 printSlice(s1)
23 printSlice(s2)
24 printSlice(s3)
25 }
26 func main(){
27 sliceInit()
28 }
Out:
s1 is nil len=0 cap=0 underlying array:0x0, [] len=0 cap=0 underlying array:0x55c988, [] len=0 cap=0 underlying array:0x55c988, []
2 切片长度与容量
切片的长度就是它所包含的元素个数。
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s = s[:0]
printSlice(s)
// Extend its length.
s = s[:4]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
Out:
len=6 cap=6 underlying array:0xc04200a2a0, [2 3 5 7 11 13] len=0 cap=6 underlying array:0xc04200a2a0, [] len=4 cap=6 underlying array:0xc04200a2a0, [2 3 5 7] len=2 cap=4 underlying array:0xc04200a2b0, [5 7]
3 赋值与传参
1 func sliceT() {
2 arrayA := [5]int{100, 200, 300, 400, 500}
3 fmt.Printf("arrayA: %p, %v\n", arrayA, arrayA)
4 fmt.Printf("arrayA: %p, %v\n", &arrayA, arrayA)
5
6 fmt.Printf("arrayA: %p, %v\n", &arrayA[0], arrayA)
7 fmt.Printf("arrayA: %p, %v\n", &arrayA[1], arrayA)
8 fmt.Printf("arrayA: %p, %v\n", &arrayA[2], arrayA)
9 fmt.Printf("arrayA: %p, %v\n", &arrayA[3], arrayA)
10 fmt.Printf("arrayA: %p, %v\n", &arrayA[4], arrayA)
11
12 slice := arrayA[1:3:4]
13 fmt.Printf("slice: %p, %v\n", slice, slice)
14 fmt.Printf("slice: %p, %v\n", &slice[0], slice)
15 fmt.Printf("slice: %p, %v\n", &slice[1], slice)
16
17 slice[0] = 0
18 fmt.Printf("slice: %p, %v\n", slice, slice)
19 fmt.Printf("arrayA: %p, %v\n", &arrayA, arrayA)
20
21 }
Out
3 arrayA: %!p([5]int=[100 200 300 400 500]), [100 200 300 400 500] 4 arrayA: 0xc04206c030, [100 200 300 400 500]
6 arrayA: 0xc04206c030, [100 200 300 400 500] 7 arrayA: 0xc04206c038, [100 200 300 400 500] 8 arrayA: 0xc04206c040, [100 200 300 400 500] 9 arrayA: 0xc04206c048, [100 200 300 400 500] 10 arrayA: 0xc04206c050, [100 200 300 400 500]
13 slice: 0xc04206c038, [200 300] 14 slice: 0xc04206c038, [200 300] 15 slice: 0xc04206c040, [200 300]
18 slice: 0xc04206c038, [0 300] 19 arrayA: 0xc04206c030, [100 0 300 400 500]
2~4
一个数组变量表示整个数组,它不是指向第一个元素的指针(不像 C 语言的数组)因此数组名通过%p 无法打印地址。 当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。 (为了避免复制数组,可以传递一个指向数组的指针)
6~9
int 在64机器上占8个字节
12~15
切片语法 a[ low:high:cap ]; cap 表示切片容量
切片名通过%p 打印,输出的是切片所引用的底层数组的地址
18~19
改变切片元素值就是改变其引用的数组的对应元素值
1 func sliceT() {
2 s := []int{1,2,3,4,5}
3 fmt.Printf("underlying array: %p, slice addr: %p\n", s, &s)
4 changeSlice(s)
5 fmt.Println(s)
6 }
7
8 func changeSlice(s []int) {
9 fmt.Printf("underlying array: %p, param slice addr: %p\n", s, &s)
10 s[1] = -1
11 }
Out:
underlying array: 0xc04206c030, slice addr: 0xc04204a3a0 underlying array: 0xc04206c030, param slice addr: 0xc04204a400 [1 -1 3 4 5]
1 func sliceT1() {
2 s := []int{1,2,3,4,5}
3 fmt.Printf("underlying array: %p, slice addr: %p\n", s, &s)
4 changeSlice1(s)
5 fmt.Println(s)
6 }
7
8 func changeSlice1(s []int) {
9 fmt.Printf("underlying array: %p, param slice addr: %p\n", s, &s)
10 s = append(s, 1)
11 }
Out:
underlying array: 0xc04200a2a0, slice addr: 0xc0420023e0 underlying array: 0xc04200a2a0, param slice addr: 0xc042002440 [1 2 3 4 5]
切片作为函数参数传递时是值传递,会拷贝一个切片,但形参和实参,拥有相同的底层数组引用。
更多内容: https://blog.go-zh.org/go-slices-usage-and-internals
https://www.jianshu.com/p/030aba2bff41