ProgrammierungGo-Entwickler

Was sind die eingebauten Funktionen append, len und cap in Go, wie funktionieren sie auf Sprachebene und welche versteckten Gefahren sind mit der Verwendung von Slices verbunden?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In Go spielen die eingebauten Funktionen append, len und cap eine Schlüsselrolle bei der Arbeit mit Slices.

  • len(slice) gibt die Anzahl der Elemente im Slice zurück.
  • cap(slice) gibt die Kapazität des Slices zurück — die maximale Anzahl von Elementen, bevor neuer Speicher zugewiesen wird.
  • append(slice, elems ...T) führt bei unzureichender Kapazität zur Erstellung eines neuen Arrays (und damit eines neuen zugrunde liegenden Speichers), was die Semantik der Übergabe des Slices unerwartet ändern kann.

Beispiel:

arr := []int{1,2,3} arr2 := append(arr, 4) // arr2 kann im selben oder in einem neuen backing array sein, abhängig von cap(arr)

Details:

  • Wenn Sie append zu einem Slice durchführen, das aus einem anderen Slice (oder Array) "abgeschnitten" wurde, kann ein side-effect auftreten: die Änderung der ursprünglichen Daten.
  • Bei der Übergabe von Slices in Funktionen wirken len/cap nur auf den "sichtbaren" Teil.
  • Bei append mit Überschreitung von cap wird ein neues Array erstellt, das alte bleibt unberührt.

Fangfrage

Was passiert, wenn einem Slice ein Stück "abgeschnitten" und ein Element über append hinzugefügt wird? Wirkt sich das auf das ursprüngliche Array aus?

Antwort: Wenn cap es zulässt, wird append das Element "am Ende" des ursprünglichen Arrays speichern, und die Änderungen sind durch alle Slices sichtbar, die auf dasselbe Array verweisen.

Beispiel:

a := []int{1,2,3,4} b := a[:2] // [1 2], len=2, cap=4 b = append(b, 10) // a ändert sich: a -> [1, 2, 10, 4]

Beispiele tatsächlicher Fehler


Geschichte

Im Team wurden Elemente zu einem untergeordneten Slice hinzugefügt, und unerwartet änderten sich die Daten im übergeordneten Array — dies führte zu einer Inkonsistenz in der Geschäftslogik und äußerst schwierigen Bugs beim Debuggen der Aufgabenverteilung zwischen Benutzern.


Geschichte

Bei einem erneuten Aufruf von append auf einem großen Slice wurde erwartet, dass das neue Array immer neu zugewiesen wird, aber in Wirklichkeit arbeiteten mehrere Teile des Systems weiterhin mit demselben "backing array", was eine race condition und Datenkorruption verursachte.


Geschichte

Ein Entwickler wies ein Slice fester Größe mit make zu, machte aber einen Fehler und tauschte die Argumente: make([]int, cap, len). Infolgedessen arbeitete die auf Kapazität ausgerichtete Logik unerwartet auf die Länge, was eine Panik beim Überschreiten von s[0:len] auslöste.