🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、切片定义 Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。 #### 1、语法: ~~~ var identifier []type ~~~ 注:切片不需要说明长度。 #### 2、使用**make()**函数来创建切片: ~~~ var slice1 []type = make([]type, len) 也可以简写为 slice1 := make([]type, len) ~~~ #### 3、也可以指定容量,其中**capacity**为可选参数。 ~~~ make([]T, length, capacity) ~~~ 注:这里 len 是数组的长度并且也是切片的初始长度。 #### 4、切片的类型 切片(slice)是对数组一个连续片段的引用,所以切片是一个引用类型。 #### 5、切片的结构 切片有3个字段的数据结构:一个是指向底层数组的指针,一个是切片的长度,一个是切片的容量。 #### 切片实例 ~~~ package main import "fmt" func main() { //初始化切片 a1 := make([]int, 3) a1[0] = 1 a1[1] = 2 a1[2] = 3 fmt.Println("a1的值为", a1) a2 := []int{1, 2, 3} fmt.Println("a2的值为", a2) } ~~~ 执行结果: a1的值为 [1 2 3] a2的值为 [1 2 3] ## 二、 len() 和 cap() 函数 切片是可索引的,并且可以由 len() 方法获取长度。 切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。 ~~~ package main import "fmt" func printSlice(x []int) { fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) } func main() { //初始化切片 a1 := make([]int, 3) a1 = append(a1, 1) fmt.Println("a1的值为", a1) printSlice(a1) } ~~~ 执行结果: a1的值为 [0 0 0 1] len=4 cap=6 slice=[0 0 0 1] ## 三、空(nil)切片 ~~~ package main import "fmt" func main() { var numbers []int printSlice(numbers) if numbers == nil { fmt.Printf("切片是空的") } } func printSlice(x []int) { fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) } ~~~ 执行结果: len=0 cap=0 slice=[] 切片是空的 ## 四、切片截取 ~~~ package main import "fmt" func main() { /* 创建切片 */ numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} /* len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8] */ printSlice(numbers) /* 打印原始切片 */ //[0 1 2 3 4 5 6 7 8] fmt.Println("numbers ==", numbers) /* 打印子切片从索引1(包含) 到索引4(不包含)*/ //[1 2 3] fmt.Println("numbers[1:4] ==", numbers[1:4]) /* 默认下限为 0*/ //[0 1 2] fmt.Println("numbers[:3] ==", numbers[:3]) /* 默认上限为 len(s)*/ //[4 5 6 7 8] fmt.Println("numbers[4:] ==", numbers[4:]) numbers1 := make([]int, 0, 5) //len=0 cap=5 slice=[] printSlice(numbers1) /* 打印子切片从索引 0(包含) 到索引 2(不包含) */ number2 := numbers[:2] //len=2 cap=9 slice=[0 1] printSlice(number2) } func printSlice(x []int) { fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) } ~~~ 运行结果: len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8] numbers == [0 1 2 3 4 5 6 7 8] numbers[1:4] == [1 2 3] numbers[:3] == [0 1 2] numbers[4:] == [4 5 6 7 8] len=0 cap=5 slice=[] len=2 cap=9 slice=[0 1] ## 五、append() 和 copy() 函数 如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。 下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。 ~~~ package main import "fmt" func main() { var numbers []int printSlice(numbers) /* 允许追加空切片 */ numbers = append(numbers, 0) printSlice(numbers) /* 向切片添加一个元素 */ numbers = append(numbers, 1) printSlice(numbers) /* 同时添加多个元素 */ numbers = append(numbers, 2, 3, 4) printSlice(numbers) /* 创建切片 numbers1 是之前切片的两倍容量*/ numbers1 := make([]int, len(numbers), (cap(numbers))*2) /* 拷贝 numbers 的内容到 numbers1 */ copy(numbers1, numbers) printSlice(numbers1) } func printSlice(x []int) { fmt.Printf("list=%v\n", x) } ~~~ 执行结果: list=[] list=[0] list=[0 1] list=[0 1 2 3 4] list=[0 1 2 3 4] ## 六、切片的定义 方式一:通过make内置函数来创建切片。基本语法: var切片名\[type = make(\[\], len,\[cap\]) ![](https://img.kancloud.cn/98/82/9882406ed892300195da60f7f1775301_689x284.png) 方式二:定一个切片,直接就指定具体数组,使用原理类似make的方式。 ![](https://img.kancloud.cn/03/01/0301960481739079340a43fd7e2ffc3d_689x116.png) ## 七、切片的遍历 ``` package main import "fmt" func main(){         //定义切片:         slice := make(\[\]int,4,20)         slice\[0\] = 66         slice\[1\] = 88         slice\[2\] = 99         slice\[3\] = 100         //方式1:普通for循环         for i := 0;i < len(slice);i++ {                 fmt.Printf("slice\[%v\] = %v \\t" ,i,slice\[i\])         }         fmt.Println("\\n------------------------------")         //方式2:for-range循环:         for i,v := range slice {                 fmt.Printf("下标:%v ,元素:%v\\n" ,i,v)         } } ``` ## 八、扩容机制 ![](https://img.kancloud.cn/35/95/359543465a85b26b6371b7b96d020cb9_689x541.png) ## 九、slice为什么不是线程安全 ![](https://img.kancloud.cn/47/a4/47a40837507916697cb641378f7d6a1b_689x456.png)