對GO切片的無知,我所踩下的坑

需求背景:

從切片中刪除指定元素

廢話不多說直接上代碼

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爲證:

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章