Go语言复合数据类型(2)–切片 – 21运维
通知: .-...

Go语言复合数据类型(2)–切片

GO 21运维 571浏览

切片
切片是动态分配大小的连续空间,与数组不一样的是,数组是固定连续空间。
切片(slice)是变长的同类型元素的序列,切片主要用于引用数组,提供了访问数组连续部分或全部元素的功能,切片可以理解成数组的一个子集,是一个动态的数组。
切片由指向数组的指针、长度和容量三个部分组成:长度为当前切片元素的数目,容量为当前切片可以容纳最多的元素数目。
可以使用内置的len()函数返回当前切片的长度,cap()函数返回当前切片的容量。
访问切片元素和数组一样,也可以通过索引下标。 0《=长度《=容量

1,从数组或者切片声明中声明切片。
var 切片变量名 []Type

未初始化切片默认是nil,长度和容量都是0。

package main

import "fmt"
func main(){
   //a := [4]int{1,2,3,4}
   var slice1 []int
   fmt.Printf("len: %d ,cap:%d\n",len(slice1),cap(slice1))
   if slice1 == nil {
      fmt.Println("切片为空")
   }
}

输出结果:
len: 0 ,cap:0
切片为空
2,初始化语法
切片名 = 数组名[开始位置:结束位置]
说明:
(1)其中数组名,是已经定义好的数组。
(2)
开始位置:目标数组元素下标索引;
结束位置:目标数组元素长度。
如果开始位置为空,则默认使用0;如果结束位置为空,默认设置为数组长度。这里的结束索引下标有歧义,个人理解成结束位置为目标数组的长度。
(3)也可以初始化直接定义一个新数组。

package main

import "fmt"
func main(){
   array := [7]int{1,2,3,4,5,6,7}
   var slice1 []int
   var slice2 []int
   var slice3 []int
   slice1 = array[2:4]
   slice2 = array[0:0]
   slice3 = array[:]

   fmt.Printf("len: %d ,cap:%d\n",len(slice1),cap(slice1))
   if slice1 == nil {
      fmt.Println("切片为空")
   }

   //打印整个切片
   fmt.Println(slice1)
   fmt.Println(slice2)
   fmt.Println(slice3)


   //取切片的最后一个元素
   fmt.Println(slice1[len(slice1)-1])

   //取切片开始和结束索引都是0的元素
   fmt.Println(slice2)

输出结果:
len: 2 ,cap:5
[3 4]
[]
[1 2 3 4 5 6 7]
4
[]

切片取值说明:
(1)取出的元素数量为:结束位置 – 开始位置;
(2)取出元素不包含结束位置对应的索引,切片最后一个元素使用 slice[len(slice)-1] 获取;
(3)当缺省开始位置时,表示从连续区域开头到指定的结束位置;
(4)当缺省结束位置时,表示从开始位置到整个连续区域末尾;
(5)两者同时缺省时,与切片本身等效;
(6)两者同时为 0 时,等效于空切片,一般用于切片复位。

案例1:1月份分别取出上旬、中旬和下旬,表示原有的切片,以及重置切片

package main

import "fmt"

func main(){
   //定义1月份31天
   var month [31]int
   for i:=0;i<31;i++{
      month[i] = i+1
   }
   fmt.Println(month)

   var  (
      shangxun []int = month[0:10]
      zhongxun []int = month[10:20]
      xiaxun []int = month[20:]
      //整个月
      month1  []int = month[:]
      //清空切片
      month2 []int = month[0:0]
   )
   fmt.Println(shangxun)
   fmt.Println(zhongxun)
   fmt.Println(xiaxun)
   fmt.Println(month1)  //fmt.Println(month[]:)
   fmt.Println(month2)  //fmt.Println(month[0:0])

}

输出结果:
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20]
[21 22 23 24 25 26 27 28 29 30 31]
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[]

3,声明切片(原始标准声明切片格式语法,一般我们是从某一个数组或者切片中生成切片)
var 变量名 []Type

package main

import "fmt"

func main(){
   var  strSlice  []string //声明一个字符串切片
   var  numSlice  []int    //声明一个整型切片
   var emptySlice []int = []int{}  //声明一个空切片
   //
   fmt.Println(len(strSlice),len(numSlice),len(emptySlice))
   fmt.Println(strSlice,numSlice,emptySlice)
   if emptySlice == nil {
      fmt.Printf("emptySlice为空")
   }
   if emptySlice != nil {
      fmt.Printf("emptySlice为空")
   }
}

输出结果:
0 0 0
[] [] []
emptySlice为空
说明:
切片是不支持比较操作,因为切片是动态分配的!切片只允许和nil做比较。

4,使用内建函数make()构造切片
可以使用go内置函数make()创建一个切片,格式:
make([]Type ,size,cap)
说明:
[]Type:切片类型
size:切片实际长度
cap:预分配切片元素最大容量。这个只是提前分配内存空间,以后大于这个值也没问题。提前分配可以降低多次分配空间造成的性能问题。

容量可以不写,此时等于长度;make()内置函数里边的参数用逗号隔开。

package main

import "fmt"
func main(){
   array := [10]int{1,2,3,4,5,6,7,8,9,10}
   var slice1 []int =make([]int,7,9)
   var slice2 []int = make([]int,7,10)
   var slice3 []int = make([]int,7)
   slice1 = array[:10]

   fmt.Printf("len:%d,cap:%d\n",len(slice1),cap(slice1))
   fmt.Printf("len:%d,cap:%d\n",len(slice2),cap(slice2))
   fmt.Printf("len:%d,cap:%d\n",len(slice3),cap(slice3))
   fmt.Println(slice1)
   fmt.Println(slice2)
   fmt.Println(slice3)
}

输出结果:
len:10,cap:10
len:7,cap:10
len:7,cap:7
[1 2 3 4 5 6 7 8 9 10]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]

5,只用内建函数append()为切片添加元素

使用内建函数append()可以动态的为切片添加元素。其中cap容量是根据之前切片容量的2倍进行扩充。
append()可以直接添加具体元素,也可以添加切片。
语法:
slice = append(slice,a,b,c)
或者
slice1 = append(slice1,slice2….)

ps:添加切片的时候,需要切片名字加… 进行列表添加。

package main

import "fmt"
func main(){
   array := [10]int{1,2,3,4,5,6,7,8,9,10}
   slice1 := array[0:5]
   slice2 := array[5:]
   slice3 := array[0:0]
   
   //为切片slice2添加元素
   slice2 =append(slice2,11,12,13)
   //为切片slice3添加切片
   slice3 =append(slice1,slice2...)
   fmt.Printf("len:%d,cap:%d,%v\n",len(slice1),cap(slice1),slice1)
   fmt.Printf("len:%d,cap:%d,%v\n",len(slice2),cap(slice2),slice2)
   fmt.Printf("len:%d,cap:%d,%v\n",len(slice3),cap(slice3),slice3)
}

输出结果:
len:5,cap:10,[1 2 3 4 5]
len:8,cap:10,[6 7 8 9 10 11 12 13]
len:13,cap:20,[1 2 3 4 5 6 7 8 9 10 11 12 13]

6,通过go内置函数copy()进行切片复制
格式:
copy(目标切片,原始切片)
返回成功复制的元素个数,等于两个切片中较小的长度。
ps:
(1)如果原始目标切片本身为空,则原始切片即使复制过来,目标切片依旧是空。所以需要对目标切片进行初始化。
(2)原始切片复制到目标切片以后,目标切片的所有数据都会被覆盖,但是只覆盖目标切片元素的对应的个数数量,不会等同于源切片。

package main

import "fmt"

func main(){
   array := [10]int{1,2,3,4,5,6,7,8,9,10}
   slice1 := array[0:10]
   slice2 := array[5:10]
   copy(slice2,slice1)
   fmt.Printf("len:%d,cap:%d,slice2:%v\n",len(slice2),cap(slice2),slice2)
}

输出结果:
len:5,cap:5,slice2:[1 2 3 4 5]

6,删除切片元素
go没有直接的内置函数可以删除,但是可以通过切片自身以及append()来间接实现删除元素。
案例:删除2。输出新的切片。

package main

import "fmt"

func main(){
   array := [5]int{1,2,3,4,5}
   const x int =2
   slice1 := array[:x]
   slice2 := array[x+1:]
   fmt.Println(slice1,slice2)
   slice := append(slice1, slice2...)
   fmt.Println(slice)

输出结果:
[1 2] [4 5]
[1 2 4 5]

7,切片的切片【了解】
某一个已经存在的切片,也可以声明新切片,新切片会基于已经存在的切片。 归根结底,切片的原理是不变的。

总结:
什么是切片,切片如何取值【核心:开始位置和结束位置的灵活使用】,切片的追加、复制以及删除如何实现。

转载请注明:21运维 » Go语言复合数据类型(2)–切片