首頁  >  文章  >  後端開發  >  為什麼 `append(x, x...)` 將切片複製到 Go 中的新支援數組中?

為什麼 `append(x, x...)` 將切片複製到 Go 中的新支援數組中?

PHPz
PHPz轉載
2024-02-10 11:12:23978瀏覽

为什么 `append(x, x...)` 将切片复制到 Go 中的新支持数组中?

php小編柚子將為大家解答一個常見的問題:為什麼`append(x, x...)`會將切片複製到Go中的新支援陣列中?在Go程式語言中,`append`函數用於向切片中追加元素。當我們使用`append`函數時,如果切片容量不足,Go會建立一個新的底層數組,並將原有切片中的元素複製到這個新的底層數組中。這是因為在Go中,切片是一個動態數組的引用,當切片容量不夠時,必須建立一個新的陣列來容納更多的元素。這種機制確保了切片的連續性和可擴展性,同時也帶來了一些效能上的損耗。

問題內容

在go 的切片技巧wiki 和go 庫(例如本範例)中,您有時會看到類似以下的程式碼,用於將切片複製到新的支援數組中。

// In a library at the end of a function perhaps...
return append(whateverSlice[:0:0], whateverSlice...)

// In an assignment, as in the wiki example...
b = append(a[:0:0], a...)

這是我認為我理解的內容:

  • 作為 append 的第二個參數的切片中的所有項目都會複製到新的支援數組中。
  • append 的第一個參數中,程式碼使用完整切片表達式。 (我們可以將第一個參數重寫為a[0:0:0],但如果省略,將提供第一個0。我認為這與這裡的更大含義無關。)
  • 根據規範,產生的切片應具有與原始切片相同的類型,且長度和容量應為零。
  • (同樣,不直接相關,但我知道您可以使用 copy 代替 append,而且讀起來更清晰。)

但是,我仍然無法完全理解為什麼語法 append(someslice[:0:0], someslice...) 建立一個新的支援陣列。我最初也很困惑為什麼 append 操作沒有弄亂(或截斷)原始切片。

現在我的猜測:

  • 我假設所有這些都是必要且有用的,因為如果您只分配 newslice := oldslice,那麼對一個的更改將反映在另一個中。通常,您不會想要這樣。
  • 因為我們沒有將 append 的結果分配給原始切片(這在 go 中是正常的),所以原始切片不會發生任何變化。它不會以任何方式被截斷或更改。
  • 由於anyslice[:0:0] 的長度和容量都為零,因此如果go 要將anyslice 的元素分配給結果,則必須建立一個新的支持數組。這就是建立新後備數組的原因嗎?
  • 如果 anyslice... 沒有元素會發生什麼事? go playground 上的片段表明,如果您在空切片上使用此附加技巧,則副本和原始副本最初具有相同的支援數組。 (編輯:正如評論者所解釋的,我誤解了這個片段。該片段顯示這兩個項目最初是相同的,但是都沒有支持數組。它們都指向最初為通用零值。)由於兩個切片的長度和容量都為零,因此當您在其中一個切片中添加任何內容時,該切片將獲得一個新的後備數組。所以我猜,效果還是一樣的。即append複製後兩個切片不能互相影響。
  • 這個其他遊樂場片段表明,如果切片的元素超過零,則 append 複製方法會立即產生一個新的後備數組。在這種情況下,可以說,生成的兩個切片立即分開。

我可能對此過於擔心,但我希望能更全面地解釋為什麼 append(a[:0:0], a...) 技巧起作用就是這樣。

解決方法

由於anySlice[:0:0]的長度和容量都為零,因此如果Go要將anySlice的元素分配給結果,則必須建立一個新的後備數組。這就是建立新支援數組的原因嗎?

因為容量是0,是的。

https://pkg.go.dev/[電子郵件受保護]#append

如果有足夠的容量,則會對目標進行重新切片以容納新元素。如果沒有,將會分配一個新的底層數組。

  • cap=0 對於非空切片來說是不夠的,需要分配一個新陣列。

以上是為什麼 `append(x, x...)` 將切片複製到 Go 中的新支援數組中?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除