Go教程切片

Posted 玖五二七

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go教程切片相关的知识,希望对你有一定的参考价值。

Golang中的切片是对数组的抽象和封装,切片的长度和容量不是固定的,是可以动态增加的

切片声明

var mySlice []int

字面量初始化切片

mySlice1 := []int1, 2, 3
fmt.Println(mySlice1)

这里和数组的区别很明显的是数组只需要在[]里面填个值就成了数组,不填,则是切片

切片运算符

与Python相同,切片可以进行切片操作

Slice[startIndex : endIndex] 将返回一个新切片

sl1 := mySlice1[0 : len(mySlice1)-1]
fmt.Println(sl1)  // [1 2]

sl1 := mySlice1[0 : len(mySlice1)]
fmt.Println(sl1)  // [1 2 3]

注意:这里的endIndex是不包含最后一个索引的,即如果是Slice[i, j],实际上返回的数据是(i, j-1),如 mySlice1[0: 2] 实际返回 [1,2]

如果需要包括最后一个数值,需要在其基础上+1,但是不能超过切片本身的长度,否则会报错

 // panic: runtime error: slice bounds out of range [:4] with capacity 3
 sl1 = mySlice1[0:4]

切片的省略写法

sl1 = mySlice[: 3] // sl1 = mySlice[0: 3]
sl1 = mySlice[2:]   // sl1 = mySlice[2: len(mySlice)]

如上所示

  • 省略:前面的值代表前端默认填0
  • 省略:后面的值,则取该切片后面所有的值

基于数组切片的相互影响

每个切片的底层都是一个数组,切片仅仅是这个底层数组的一个视图

当使用make或字面量创建切片的时候,底层数组会被自动的创建出来。

下面的代码很有意思,可以让我们加深切片的理解

// 声明和初始化一个数组
  arr := [5]int1, 2, 3, 4, 5
  sl1 = arr[:3] // sl1切片由该数组而来
  sl2 := arr[0:]
  fmt.Println(sl1)
  fmt.Println(sl2)
  sl1[0] = 6       // 修改切片的第1个值
  fmt.Println(sl1) //
  fmt.Println(arr) // arr的值也被修改
  fmt.Println(sl2) // sl2的值也被修改

由于上述的实验, 我们应该用切片字面量和make来创建切片,而不是像上面这样基于数组。避免修改了切片的值会影响到原来的数组

使用append动态添加数据

apppend将返回一个和原切片完全相同并且尾部追加新元素的新切片

这个新切片与原切片不同的底层数组。当append发生在原数组地址空间无法扩展时,将重新开辟一块内存,把当前的元素全部拷贝过去,再在尾部追加新元素。而这一切都是append内部发生的,所以无法确定新切片是否和老切片共享底层数组。

因此我们在append以后需要把新切片赋值给原来的切片,这样就比较安全。

sl3 := append(sl1, 4, 5) // 危险,sl3和sl1不确定是否互相影响
sl1 := append(sl1, 4, 5) // OK,还是sl1上操作

切片的零值

与数组一样,如果访问了一个未赋值的切片,则会得到它的0值

  // 声明一个切片
  var declearSlice []int
  // 打印decleareClice的原始状态
  fmt.Printf("declear clice %#v\\n", declearSlice)
  // 可以直接append给nil的切片
  declearSlice = append(declearSlice, 1)
  // 再次打印该切片
  fmt.Printf("declear clice %#v\\n", declearSlice)
  fmt.Println(len(declearSlice))

运行结果如下

declear clice []int(nil)
declear clice []int1
1

以上的实验说明go对切片进行了特殊处理,即使是nil切片也可以正常append操作

但是如果是赋值,则会发生panic

var dSlice []int
dSlice[0] = 1 // runtime error: index out of range [0] with length 0

所以append是安全的,但赋值是危险的,必须要判断该切片长度是否达标。

命令行参数切片

当我们运行程序时,主函数main是没有参数的,但是操作系统会把参数以切片的形式带过来,在golang中叫做os.Args

for index, value := range os.Args 
    fmt.Println(index, value)
  

go run main.go first second

执行上面的代码后,我们可以得到以下的结果

0 C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\go-build4120744967\\b001\\exe\\main.exe
1 first
2 second

第一个元素是程序的名称,我们从第2个元素开始取,则能得到我们自定义的参数

  for index, value := range os.Args 
    if index == 0 
      continue
    
    fmt.Println(index, value)
  

修改一下代码,我们则可以看到只有

1 first
2 second

以上是关于Go教程切片的主要内容,如果未能解决你的问题,请参考以下文章

go语言之字符串指针数组切片

Go 系列教程 —— 11. 数组和切片

Go - 函数/方法 的 变参

go语言基础切片,map

go语言基础切片,map

Go语言 使用append() 为切片动态添加元素