当前位置:   article > 正文

Go教程(六)切片_panic: runtime error: slice bounds out of range [:

panic: runtime error: slice bounds out of range [:1] with length 0

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

切片声明

var mySlice []int
  • 1

字面量初始化切片

mySlice1 := []int{1, 2, 3}
fmt.Println(mySlice1)

  • 1
  • 2
  • 3

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

切片运算符

与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]
  • 1
  • 2
  • 3
  • 4
  • 5

注意:这里的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]
  • 1
  • 2

切片的省略写法

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

如上所示

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

基于数组切片的相互影响

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

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

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

// 声明和初始化一个数组
  arr := [5]int{1, 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的值也被修改
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

使用append动态添加数据

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

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

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

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

切片的零值

与数组一样,如果访问了一个未赋值的切片,则会得到它的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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

运行结果如下

declear clice []int(nil)
declear clice []int{1}
1
  • 1
  • 2
  • 3

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

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

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

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

命令行参数切片

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

for index, value := range os.Args {
    fmt.Println(index, value)
  }
  • 1
  • 2
  • 3

go run main.go first second

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

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

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

  for index, value := range os.Args {
    if index == 0 {
      continue
    }
    fmt.Println(index, value)
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

1 first
2 second
  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/206400
推荐阅读
相关标签
  

闽ICP备14008679号