十六、Go基础编程:复合类型—切片slice

超、凢脫俗 2022-05-16 15:57 376阅读 0赞
  1. 概述

数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。显然这种数据结构无法完全满足开发者的真实需求。Go语言提供了数组切片(slice)来弥补数组的不足。

切片并不是数组或数组指针,它通过内部指针和相关属性引⽤数组⽚段,以实现变⻓⽅案。

slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。
SouthEast

2. 切片的创建

slice和数组的区别:声明数组时,方括号内写明了数组的长度或使用…自动计算长度,而声明slice时,方括号内没有任何字符

  1. var s1 []int //声明切片和声明array一样,只是少了长度,此为空(nil)切片
  2. s2 := []int{}
  3. //make([]T, length, capacity) //capacity可以省略,则和length的值相同
  4. var s3 []int = make([]int, 0)
  5. s4 := make([]int, 0, 0)
  6. s5 := []int{1, 2, 3} //创建切片并初始化

3. 切片的操作

3.1 切片截取

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzg4NzI0OA_size_16_color_FFFFFF_t_70

示例说明:watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzg4NzI0OA_size_16_color_FFFFFF_t_70 1

3.2 切片和底层数组关系

  1. s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
  2. s1 := s[2:5] //[2 3 4]
  3. s1[2] = 100 //修改切片某个元素改变底层数组
  4. fmt.Println(s1, s) //[2 3 100] [0 1 2 3 100 5 6 7 8 9]
  5. s2 := s1[2:6] // 新切片依旧指向原底层数组 [100 5 6 7]
  6. s2[3] = 200
  7. fmt.Println(s2) //[100 5 6 200]
  8. fmt.Println(s) //[0 1 2 3 100 5 6 200 8 9]

3.3 内建函数

3.3.1 append

append函数向 slice 尾部添加数据,返回新的 slice 对象:

  1. var s1 []int //创建nil切换
  2. //s1 := make([]int, 0)
  3. s1 = append(s1, 1) //追加1个元素
  4. s1 = append(s1, 2, 3) //追加2个元素
  5. s1 = append(s1, 4, 5, 6) //追加3个元素
  6. fmt.Println(s1) //[1 2 3 4 5 6]
  7. s2 := make([]int, 5)
  8. s2 = append(s2, 6)
  9. fmt.Println(s2) //[0 0 0 0 0 6]
  10. s3 := []int{1, 2, 3}
  11. s3 = append(s3, 4, 5)
  12. fmt.Println(s3)//[1 2 3 4 5]

append函数会智能地底层数组的容量增长,一旦超过原底层数组容量,通常以2倍容量重新分配底层数组,并复制原来的数据:

  1. func main() {
  2. s := make([]int, 0, 1)
  3. c := cap(s)
  4. for i := 0; i < 50; i++ {
  5. s = append(s, i)
  6. if n := cap(s); n > c {
  7. fmt.Printf("cap: %d -> %d\n", c, n)
  8. c = n
  9. }
  10. }
  11. /*
  12. cap: 1 -> 2
  13. cap: 2 -> 4
  14. cap: 4 -> 8
  15. cap: 8 -> 16
  16. cap: 16 -> 32
  17. cap: 32 -> 64
  18. */
  19. }

3.3.2 copy

函数 copy 在两个 slice 间复制数据,复制⻓度以 len 小的为准,两个 slice 可指向同⼀底层数组。

  1. data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
  2. s1 := data[8:] //{8, 9}
  3. s2 := data[:5] //{0, 1, 2, 3, 4}
  4. copy(s2, s1) // dst:s2, src:s1
  5. fmt.Println(s2) //[8 9 2 3 4]
  6. fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]

4. 切片做函数参数

  1. func test(s []int) { //切片做函数参数
  2. s[0] = -1
  3. fmt.Println("test : ")
  4. for i, v := range s {
  5. fmt.Printf("s[%d]=%d, ", i, v)
  6. //s[0]=-1, s[1]=1, s[2]=2, s[3]=3, s[4]=4, s[5]=5, s[6]=6, s[7]=7, s[8]=8, s[9]=9,
  7. }
  8. fmt.Println("\n")
  9. }
  10. func main() {
  11. slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
  12. test(slice)
  13. fmt.Println("main : ")
  14. for i, v := range slice {
  15. fmt.Printf("slice[%d]=%d, ", i, v)
  16. //slice[0]=-1, slice[1]=1, slice[2]=2, slice[3]=3, slice[4]=4, slice[5]=5, slice[6]=6, slice[7]=7, slice[8]=8, slice[9]=9,
  17. }
  18. fmt.Println("\n")
  19. }

发表评论

表情:
评论列表 (有 0 条评论,376人围观)

还没有评论,来说两句吧...

相关阅读

    相关 go 复合类型

    1、pointer:指针,默认值:nil 指针是一个代表着某个内存地址的值。这个内存地址往往是在内存中存储的另一个变量的值的起始位置,go语言对指针的支持介于java语言