1. 场景1
slice元素删除时,由于下标越界会报错“slice bounds out of range", 代码示例如下:
package main import ( "fmt" ) func main() { var numList []int numList = append(numList, 1) numList = append(numList, 2) fmt.Println("numList len:", len(numList)) numList = append(numList[0:1], numList[2:]...) // 第一次:正常删除下标为1的元素 fmt.Println("numList:", numList) fmt.Println("numList len:", len(numList)) numList = append(numList[0:1], numList[2:]...) // 第二次:numList[2]越界了 fmt.Println("numList:", numList) }
运行结果如下:
numList len: 2 numList: [1] numList len: 1 panic: runtime error: slice bounds out of range goroutine 1 [running]: panic(0x49b100, 0xc04200c060) c:/go/src/runtime/panic.go:500 +0x1af main.main() E:/Study-Data/GO/Test/src/dbTest/main.go:17 +0x5f7
分析:
第一次调用numList[2:]...,其实下标2已结越界了,但是执行并不会报错,猜测原因可能是golang特殊处理了,为了方便删除切片的最后一个元素,否则,开发起来比较麻烦,每次删除都需要判断是否是最后一个元素,删除最后一个元素都得加if else判断;
第二次调用numList[2:]...,由于下标已经比slice总长度还要大1, 因此报错;
2. 场景2
“slice bounds out of range", 另外一种场景下,出错比较不容易被发现,如需要在循环中删除元素的情况, 示例代码如下:
package main func main() { var numList []int numList = append(numList, 1) numList = append(numList, 2) numList = append(numList, 3) for i, v := range numList { if 1 == v { numList = append(numList[0:i], numList[i+1:]...) // 第一次:正常删除下标为i的元素 } if 3 == v { numList = append(numList[0:i], numList[i+1:]...) // 第二次:删除下标为i的元素报错 } } }
分析:
在for循环中需要多次删除元素时,删除最后几个元素时很可能产生越界,而且这种越界编码时不易察觉;
若是我们需要循环删除多个切片运输,该如何处理呢?一些是一点思路,示例如下:
package main import ( "fmt" ) func main() { var srcList []int srcList = append(srcList, 1) srcList = append(srcList, 2) srcList = append(srcList, 3) fmt.Println("srcList:", srcList) var dstList []int for _, v := range srcList { if v != 1 && v != 3 { dstList = append(dstList, v) // 排除值为1和3的元素 } } fmt.Println("dstList:", dstList) }
输出如下:
srcList: [1 2 3] dstList: [2]
分析:将需要的元素重新拷贝到一个新的切片里,若切片元素比较大,则建议切片元素使用指针;