golang中慎用slice的賦值


一篇很典型的golang slice采坑記錄:https://studygolang.com/articles/6557
有如下代碼:

type AutoGenerated struct {
	Age  int    `json:"age"`
	Name string `json:"name"`
	Child []int `json:"child"`
}

func main() {
	jsonStr1 := "{\"age\": 12,\"name\": \"potter\", \"child\":[1,2,3]}"
	a := AutoGenerated{}
	json.Unmarshal([]byte(jsonStr1), &a)
	aa := a.Child
	fmt.Println(aa)
	jsonStr2 := "{\"age\": 14,\"name\": \"potter\", \"child\":[3,4,5,7,8,9]}"
	json.Unmarshal([]byte(jsonStr2), &a)
	fmt.Println(aa)
}

運行會發現,第一次打印aa時,aa是 [1,2,3],第二次打印aa時,aa就變成了[3,4,5]
這是因為兩次調用 unmarshal 時,a 里面的 Child 字段實際上是同一個 slice,剛開始第一次 unmarshal 時,a.Child = [1,2,3],其中 cap = 4。然后在第二次 unmarshal 時,給a.Child 中添加新的內容 [3,4,5,7,8,9] 時,因為 a.Child 的容量不足,因此需要重新分配底層array,但是因為 aa 對應的那個 slice 前4個位置已經被覆蓋了,因此 aa 第二次打印的值就是 [1,2,3]了

因此,在使用slice之間的賦值時,要格外小心,因為左值和右值是使用了同一個底層array,同時它們兩者何時會分拆成兩個array也無法確定。
PS:用golang的切片也是公用同一個底層array


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM