需求背景:
從切片中刪除指定元素
廢話不多說直接上代碼
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爲證: