Go语言基础之切片

1. 切片是什么?

在Go语言中,切片(slice)是一种动态数组,可以伸缩的序列。它由指向数组某个元素的指针、切片长度和切片容量组成。我们可以使用内置函数 make 来创建切片。切片的语法和数组很像,但是它比数组更加灵活。

1.1 切片的语法

切片的声明和数组类似,只是没有长度。

var a []int // 声明一个切片

使用内置函数 make 来创建切片,并指定长度和容量。

a := make([]int, 5) // 长度为5,容量为5

切片的语法中可以使用冒号分割切片的开始和结束位置。

a := []int{1, 2, 3, 4, 5} // 声明一个切片并赋值

b := a[1:3] // 从切片a中取出元素索引为1和2的元素,构成新的切片b

需要注意的是,切片不会拷贝底层数组,它只是对底层数组的引用。

1.2 切片的长度和容量

切片的长度表示其中元素的个数,可以使用内置函数 len 来获取切片的长度。

a := []int{1, 2, 3, 4, 5}

len := len(a) // 获取切片a的长度,结果为5

切片的容量表示其中可以存储的元素个数,可以使用内置函数 cap 来获取切片的容量。

a := make([]int, 5, 10) // 创建切片,长度为5,容量为10

cap := cap(a) // 获取切片a的容量,结果为10

1.3 切片与底层数组

切片是对底层数组的一个引用,改变切片中元素的值会影响到底层数组,而且多个切片可以共享同一个底层数组。

a := []int{1, 2, 3, 4, 5} // 声明一个切片并赋值

b := a[1:3] // 从切片a中取出元素索引为1和2的元素,构成新的切片b

b[0] = 6 // 修改切片b第一个元素的值为6

fmt.Println(a) // [1 6 3 4 5]

fmt.Println(b) // [6 3]

2. 切片的操作

2.1 中间添加元素

我们可以使用内置函数 append 来在切片的中间或末尾添加元素。

a := []int{1, 2, 3, 4, 5} // 声明一个切片并赋值

b := append(a[:2], 6) // 在切片a中索引为0和1之间添加元素6,并赋值给切片b

fmt.Println(a) // [1 2 6 4 5]

fmt.Println(b) // [1 2 6]

2.2 中间删除元素

我们可以使用切片的语法特性,将一个切片复制自己的一部分,来删除中间的元素。

a := []int{1, 2, 3, 4, 5} // 声明一个切片并赋值

a = append(a[:2], a[3:]...) // 删除切片a中索引为2的元素,并赋值给切片a

fmt.Println(a) // [1 2 4 5]

3. 切片的性能

切片在底层是一个指向底层数组的指针、切片长度和容量,通过这三个属性,Go语言可以自动伸缩切片。但是切片的自动伸缩也会带来性能问题。

比如,如果我们在一个长度为100的切片中添加元素,其底层数组可能不够用,需要重新分配更大的内存空间,然后复制原数组到新数组中,这个过程需要耗费时间。所以,在性能敏感的场合,应该尽量避免切片的自动伸缩。

针对切片的性能问题,我们可以使用内置函数 make 在声明的时候就为切片创建足够的空间,从而避免切片自动扩容而带来的性能影响。

4. 总结

切片是Go语言中非常重要的一种数据结构,它通过动态数组的形式实现了变长数组的功能,并且支持多个切片引用同一个底层数组。但是,由于切片底层是数组,所以容易引发内存泄露等性能问题,需要注意。

后端开发标签