需求背景:
从切片中删除指定元素
废话不多说直接上代码
package main
import (
"fmt"
)
var datas []int
var filter int
func init() {
datas = append(datas, 11, 22, 33, 44)
filter = 11
}
func main() {
filterData(datas, filter)
fmt.Println("datas:", datas)
}
// 从recordedDatas 删除filter中的指定的元素
func filterData(recordedDatas []int, filter int) {
for i, recorded := range recordedDatas {
if recorded == filter {
recordedDatas = append(recordedDatas[:i], recordedDatas[i+1:]...)
break
}
}
}
输出
datas: [22 33 44 44]
输出结果应该是这样的才对啊:
res: [33 44]
问题排查
切片类型作为引用类型,引用类型在函数间的传递的是变量的地址,然而这个地址其实也是一个值。
所以函数中的recordedDatas参数和全局变量datas指向了同一个底层数组
recordedDatas = append(recordedDatas[:i], recordedDatas[i+1:]...)
这段代码的意图就是想每一次循环就将filter中的指定元素从recordedDatas中删除,
问题就出现在该代码中:
当循环第一次进入到该代码中时上述代码可以替换为
recordedDatas = append(recordedDatas[:0], recordedDatas[0+1:]...)
recordedDatas = [22 33 44]
这样一看觉得程序没啥问题啊,但是我们上面说过recordedDatas参数和全局变量datas指向了同一个底层数组,而append操作时,当前切片的容量是够的,所以不会重新创建新的切片。
append(recordedDatas[:0], recordedDatas[0+1:]…) 操作将 22 33 44 append到recordedDatas的同时,由于recordedDatas和datas指向的都是同一个底层数组,所以此时当前的datas数据为
datas = [22 33 44 44]
下图debug为证: