Heim  >  Artikel  >  Backend-Entwicklung  >  Warum kopiert „append(x, x...)“ das Slice in ein neues Backing-Array in Go?

Warum kopiert „append(x, x...)“ das Slice in ein neues Backing-Array in Go?

PHPz
PHPznach vorne
2024-02-10 11:12:23981Durchsuche

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

php-Editor Youzi wird eine häufig gestellte Frage für alle beantworten: Warum kopiert „append(x, x...)“ das Slice in das neue Support-Array in Go? In der Programmiersprache Go wird die Funktion „append“ verwendet, um Elemente an ein Slice anzuhängen. Wenn wir die Funktion „Anhängen“ verwenden und die Slice-Kapazität nicht ausreicht, erstellt Go ein neues zugrunde liegendes Array und kopiert die Elemente im ursprünglichen Slice in das neue zugrunde liegende Array. Dies liegt daran, dass in Go ein Slice ein Verweis auf ein dynamisches Array ist. Wenn die Slice-Kapazität nicht ausreicht, muss ein neues Array erstellt werden, um mehr Elemente aufzunehmen. Dieser Mechanismus stellt die Kontinuität und Skalierbarkeit von Slices sicher, bringt aber auch einige Leistungseinbußen mit sich.

Frageninhalt

Im Wiki mit Slicing-Tipps von go und in Go-Bibliotheken (wie in diesem Beispiel) wird manchmal Code wie der folgende zum Kopieren eines Slice in ein neues Backing-Array angezeigt.

// 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...)

Das glaube ich zu verstehen:

  • Alle Elemente im Slice, die als zweites Argument für append angegeben werden, werden in das neue Hintergrundarray kopiert.
  • Im ersten Parameter von append 的第一个参数中,代码使用完整切片表达式。 (我们可以将第一个参数重写为 a[0:0:0],但如果省略,将提供第一个 0 verwendet der Code einen vollständigen Slice-Ausdruck. (Wir könnten das erste Argument als a[0:0:0] umschreiben, aber wenn es weggelassen wird, wird das erste
  • bereitgestellt. Ich glaube nicht, dass das für die größere Bedeutung hier relevant ist.)
  • Gemäß der Spezifikation sollte der generierte Slice vom gleichen Typ wie der ursprüngliche Slice sein und eine Länge und Kapazität von Null haben.
  • copy 代替 append (Wiederum nicht direkt verwandt, aber ich weiß, dass Sie copy anstelle von
  • verwenden können, und es liest sich sauberer.)

append(someslice[:0:0], someslice...) 创建一个新的支持数组。我最初也很困惑为什么 appendAllerdings verstehe ich immer noch nicht ganz, warum die Syntax append(someslice[:0:0], someslice...) ein neues Backing-Array erstellt. Ich war anfangs auch verwirrt darüber, warum der

-Vorgang das ursprüngliche Slice nicht durcheinander gebracht (oder abgeschnitten) hat.

Jetzt meine Vermutung:
  • newslice := oldsliceIch gehe davon aus, dass all dies notwendig und nützlich ist, denn wenn Sie nur
  • zuweisen, werden sich Änderungen an dem einen im anderen widerspiegeln. Normalerweise möchte man das nicht.
  • appendDa wir das Ergebnis von
  • nicht dem Original-Slice zuweisen (was in go normal ist), passiert nichts mit dem Original-Slice. Es wird in keiner Weise gekürzt oder verändert.
  • anyslice[:0:0] 的长度和容量均为零,因此如果 go 要将 anysliceDa die Elemente von dem Ergebnis zugeordnet sind, muss ein neues Backing-Array erstellt werden. Ist das der Grund
  • , ein neues Backing-Array zu erstellen?
  • anyslice... 没有元素会发生什么? go playground 上的一个片段表明,如果您在空切片上使用此附加技巧,则副本和原始副本最初具有相同的支持数组。 (编辑:正如评论者所解释的,我误解了这个片段。该片段显示这两个项目最初是相同的,但是都没有支持数组。它们都指向最初为通用零值。)由于两个切片的长度和容量都为零,因此当您向其中一个切片添加任何内容时,该切片将获得一个新的后备数组。所以我猜,效果还是一样的。即appendWas passiert, wenn anyslice... keine Elemente hat? Ein Snippet auf dem Go-Playground zeigt, dass, wenn Sie diesen zusätzlichen Trick auf ein leeres Slice anwenden, die Kopie und das Original zunächst das gleiche Backing-Array haben. (Bearbeiten: Wie ein Kommentator erklärte, habe ich diesen Ausschnitt falsch verstanden. Der Ausschnitt zeigt, dass die beiden Projekte ursprünglich gleich waren, aber keine Arrays unterstützen. Beide verweisen auf ein generisches ) Da beide Slices eine Länge und Kapazität von Null haben, erhält dieses Slice ein neues Backing-Array, wenn Sie etwas zu einem der Slices hinzufügen. Ich vermute also, dass der Effekt immer noch derselbe ist. Das heißt, die beiden Slices können sich nach dem Kopieren nicht gegenseitig beeinflussen.
  • Dieser andere Playground-Ausschnitt zeigt, dass die append-Kopiermethode sofort ein neues Backing-Array generiert, wenn das Slice mehr als null Elemente enthält. In diesem Fall werden die beiden resultierenden Slices sozusagen sofort getrennt.

Wahrscheinlich mache ich mir darüber zu viele Sorgen, aber ich hätte gerne eine ausführlichere Erklärung warum append(a[:0:0], a...)der Trick einfach so funktioniert.

Problemumgehung

Da anySlice[:0:0] eine Länge und Kapazität von Null hat, muss Go ein neues Backing-Array erstellen, wenn es die Elemente von anySlice dem Ergebnis zuweisen möchte. Wurde deshalb das neue Backing-Array erstellt?

Denn die Kapazität ist 0, ja.

https://pkg.go.dev/[email protected]#append

Wenn genügend Kapazität vorhanden ist, wird das Ziel neu aufgeteilt, um die neuen Elemente aufzunehmen. Wenn nicht, wird ein neues zugrunde liegendes Array zugewiesen.

  • cap=0 Nicht genug für nicht leere Slices, es muss ein neues Array zugewiesen werden.

Das obige ist der detaillierte Inhalt vonWarum kopiert „append(x, x...)“ das Slice in ein neues Backing-Array in Go?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen