数组是一种可以存储一个或多个同种类型的数据结构,具有定长,支持索引访问,内存连续等特点,而切片是数组的一种延伸,长度可变,即 C++中的动态数组。

初始化

1
var arr [len]type

当然,你也可以把len省略成...它能直接预估数组的长度,而不需要手算。

而切片就是直接省略,留空即可。

1
2
var slice1 []type
slice2 := make([]type, len, cap)

切片,顾名思义,就是数组切割形成的片段,而且 slice 是引用类型,它的底层是一个数组。它的起始地址是数组的起始地址,它的长度是切片的长度,它的容量是从切片的第一个元素到数组的最后一个元素的长度。

数组与切片在内存的底层
数组与切片在内存的底层

浅拷贝和深拷贝

数组与切片的赋值都是浅拷贝,即只是拷贝了地址,而不是值。它们都是共享内存的。当其中一个值改变时,另一个值也会改变。所以想让它们不共享内存,相互独立,就需要深拷贝。

深拷贝需要使用copy函数

1
2
3
oldSlice := []int{1, 2, 3}
newSlice := make([]int, 10)
n := copy(newSlice, oldSlice)

字符串与字节切片

字符串是只读的字节切片,它的值是不可变的。而字节切片是可变的,它的值是可变的。

在内存中,一个字符串实际上是一个双字结构,即一个指向实际数据的指针和记录字符串长度的整数

字符串的底层原理
字符串的底层原理

如何相互转换呢?

1
2
byteSlice := []byte(str)
str := string(byteSlice)

课后练习

题目1

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
x := []int{2, 3, 5, 7, 11}
y := x[1:3]
fmt.Println(x, y, y[0:4])
}

答案

1
[2 3 5 7 11] [3 5] [3 5 7 11]