TL; DR:(摘要)
你只需要做切片值的副本。片類型的值是一個描述符到一個底層陣列:
slice2 := slice
現在slice2
將是指相同的,共享基礎數組等slice
被zerored後它將是可到達的。
在長:
slice := make([]int, 5)
這創建名爲[]int
類型的slice
局部變量(和將被與描述符指由make
在後臺創建大小5
的數組初始化)。它是一個分片,它是底層數組的一個連續部分的描述符,它是在後臺自動創建的。
slicesArray[0] = &slice
此存儲局部變量(名爲slice
)插入的slicesArray
第0個元素的地址。請注意,slicesArray
只是一個指針片(指針可指向[]int
類型的值,但現在無關緊要)。
因此,仍然沒有創建原始slice
的副本。
因此,當您將類型爲[]int
(這是本地變量名爲slice
)的唯一值歸零時,您只會歸零唯一的切片值(並且您將失去對其後備數組的唯一引用)。
你想在slice
被清零後保持切片值?只需製作一份(切片值)的副本。複製切片類型的值只會生成描述符的副本,不會複製後備數組;而副本將指向同一個支持數組(它的共享):
slice2 := slice // makes a copy of the slice value
slice = nil
這*(slicesArray[0])
仍將指向一個切片值爲nil
後,但我們有原片的副本(和共享支持數組)。
這樣算下來:
slicesArray[0] = &slice2
fmt.Println((*(slicesArray[0]))[3])
將打印再次25
。 Go Playground
您應該保留切片值還是指向切片?
由於切片只是相對較小的描述符,因此您應該保留並使用切片值。切片值已包含對後備陣列的「引用」。通過使用指向切片的指針添加另一個間接方向會使事情複雜化並稍微放慢速度。切片已經被設計成小巧,高效和靈活(與Go中的「真實」陣列相比)。
當然,在某些情況下,指向切片值的指針也可能很有用,例如,如果您希望創建一個類似於內建函數的函數而不返回新切片。或者,當您創建基礎類型爲切片類型的自定義類型時,並且您可以爲此類型定義修改切片值的方法(在這種情況下,指針接收器是必需的)。
此外讀數:(該文檔在詳細解釋一切)
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'
「因爲切片一旦設定爲nil垃圾收集標記的存儲區域爲髒」,這是不正確。如果任何代碼有一個指向某個東西的指針,那麼垃圾收集器就把它留下。你可以整天設置指針爲'nil',垃圾收集器沒有任何反應(**除非**指向的內容現在不再被其他任何東西指向)。 –