Einführung
In Go sind Arrays und Slices Datenstrukturen, die aus einer geordneten Reihe von Elementen bestehen. Diese Datensammlungen sind hervorragend, wenn Sie mit vielen zusammenhängenden Werten arbeiten möchten. Sie erlauben Ihnen, Werte zusammenzuhalten, kompaktere Code zu schreiben, und gleichzeitig auf mehrere Werte gleicher Art einheitliche Methoden und Operationen anzuwenden.
Obwohl Arrays und Slice in Go beide eine geordnete Reihe von Elementen sind, gibt es signifikante Unterschiede zwischen ihnen. Ein Array ist in Go eine Datenstruktur, die aus einer geordneten Reihe von Elementen besteht, deren Kapazität bei der Erstellung festgelegt ist. Nachdem das Array seine Größe allokiert hat, kann sie nicht mehr verändert werden. Eine Slice, hingegen, ist eine variablen-länge Version eines Arrays und bietet Entwicklern mehr Flexibilität, wenn sie diese Datenstrukturen verwenden. Slices repräsentieren was Sie als Arrays in anderen Sprachen denken sollten.
Aufgrund dieser Unterschiede sind bestimmte Situationen, in denen Sie einen über den anderen verwenden sollten. Wenn Sie Neue in Go sind, können Sie sich darüber schwer machen, wann man welchen zu verwenden hat. Obwohl die Vielseitigkeit der Slices sie in den meisten Fällen als angenehmster Wahl erscheinen lässt, gibt es spezielle Situationen, in denen Arrays die Leistung Ihres Programms optimieren können.
Dieser Artikel wird die Arrays und Slices genau behandeln, was dir die notige Information zur Wahl zwischen diesen Datentypen liefert. Zudem werden die am meisten verbreiteten Methoden zur Deklaration und Arbeit mit beiden Typen von Datenstrukturen erklärt. Der Tutorial beginnt mit einer Beschreibung von Arrays und der Manipulation dieser, gefolgt von einem Erklärung wie sie sich unterscheiden.
Arrays
Arrays sind eine Sammlungsdatenstruktur mit festem Elementanzahl. Da die Größe eines Arrays statisch ist, muss die Datenstruktur nur einmal Speicher allozieren, im Gegensatz zu variablen Länge Datenstrukturen, die dynamisch Speicher allozieren müssen, damit sie größer oder kleiner werden können. Da die feste Länge von Arrays sie etwas rigide machen, um mit ihnen zu arbeiten, bietet die einmalige Speicherallozierung den Vorteil höherer Geschwindigkeit und Leistung. Daher werden Entwickler typischerweise Arrays verwenden, wenn die Datenstruktur nie einen variablen Anzahl von Elementen benötigen wird.
Definition eines Arrays
Arrays werden durch Angabe der Größe des Arrays in Klammern `[ ]` gefolgt von dem Datentyp der Elemente definiert. Ein Array in Go muss alle Elemente desselben `data type` haben. Nach dem Datentyp können Sie die einzelnen Werte der Arrayelemente in runden Klammern `{ }` deklarieren.`
Das folgende ist das allgemeine Schema zur Deklaration eines Arrays:`
Hinweis: Es ist wichtig zu erinnern, dass jeder Deklaration eines neuen Arrays eine eindeutige Datentyp-Struktur zuordnet. Daher sind `[2]int` und `[3]int` zwar beide mit Integer-Elementen versehen, jedoch ihre unterschiedlichen Längen machen ihre Datentypen inkompatibel.`
Wenn Sie die Werte der Arrayelemente nicht deklarieren, ist die Voreinstellung leer, was bedeutet, dass die Elemente des Arrays leer sind. Für Integer entspricht dies `0`, und für Strings ist es ein leeres String-Element.`
Zum Beispiel ist das folgende Array `numbers` mit drei Integer-Elementen, die noch keine Werte haben:`
Wenn Sie `numbers` drucken würden, erhalten Sie die folgende Ausgabe:`
Output[0 0 0]
Wenn Sie die Werte der Elemente beim Erstellen des Arrays zuweisen möchten, platzieren Sie die Werte in runden Klammern. Ein Array von Zeichenfolgen mit festen Werten sieht wie folgt aus:`
Sie können ein Array in einer Variable speichern und es ausgeben:`
Beim Ausführen eines Programms mit den oben genannten Zeilen erhalten Sie die folgende Ausgabe:
Output[blue coral staghorn coral pillar coral elkhorn coral]
Beachten Sie, dass bei der Ausgabe des Arrays kein Unterschied zwischen den Elementen erkennbar ist, was es schwierig macht, zu erkennen, wo ein Element endet und ein anderes beginnt. Aufgrund dieser Tatsache ist es manchmal hilfreich, die Funktion fmt.Printf
zu verwenden, die Strings formatiert und anschließend auf die Bildschirmausgabe sendet. Verwenden Sie das Verb %q
mit diesem Befehl, um die Funktion anzuweisen, die Wertangaben in Anführungszeichen zu schließen:
Dadurch erhalten Sie folgendes Ergebnis:
Output["blue coral" "staghorn coral" "pillar coral" "elkhorn coral"]
Jedes Element ist jetzt in Anführungszeichen gefasst. Das Verb \n
gibt an, dem Formatter eine Zeilenumbrüche hinzuzufügen.
Nachdem Sie einen allgemeinen Überblick über die Deklaration von Arrays und deren Inhalt haben, können Sie nun zu dem Lernen gehen, wie Elemente in einem Array mit einem Indexnummern festgelegt werden.
Array- und Slicen-Indizierung
Jedes Element in einem Array (und auch in einer Slice) kann individuell durch Indizierung aufgerufen werden. Jeder Element hat eine Indexnummer, die ein int
-Wert mit der Startnummer 0
und zählt aufwärts ist.
Wir werden in den folgenden Beispielen ein Array verwenden, aber Sie könnten auch eine Slice verwenden, da sie in der Indizierung beider identisch sind.
Für das Array coral
sieht die Indizierungsübersicht wie folgt aus:
“blue coral” | “staghorn coral” | “pillar coral” | “elkhorn coral” |
---|---|---|---|
0 | 1 | 2 | 3 |
Die erste Element ist die Zeichenkette "blue coral"
, die bei Index 0
beginnt und bei Index 3
endet mit dem Element "elkhorn coral"
.
Da jeder Element in einem Slice oder Array einen zugehörigen Indexnummer hat, können wir sie wie bei anderen sequentiellen Datentypen manipulieren.
Jedes Element des Slices kann durch seine Indexnummer individuell aufgerufen werden:
Outputstaghorn coral
Die Indexnummern für dieses Slice reichen von 0-3
, wie im vorherigen Tabelle gezeigt sind. Um also einzelne Elemente zu rufen, müssen Sie folgendermaßen eine Referenz zur Indexnummer machen:
Wenn Sie das Array coral
mit einer Indexnummer auswählen, die größer als 3
ist, wird es nicht gültig sein, da es nicht valide ist:
Outputpanic: runtime error: index out of range
In Go ist es nicht möglich, indem man eine negative Zahl verwendet, um rückwärts zu indexieren, denn das wird einen Fehler hervorbringen:
Outputinvalid array index -1 (index must be non-negative)
Wir können String-Elemente eines Arrays oder Slices mit anderen Zeichenketten mit dem Operator +
konkatenieren:
OutputSammy loves blue coral
Wir konnten die Zeichenkette am Indexnummer 0
mit der Zeichenkette "Sammy loves "
konkatenieren.
Mit Indexnummern, die zu bestimmten Elementen innerhalb eines Arrays oder Slices passen, können wir jedes Element diskret auswählen und mit diesem Element arbeiten. Um dies zu demonstrieren, werde ich in der nächsten Schritt darauf hin zeigen, wie man ein Element an einer bestimmten Indexposition modifiziert.
Elemente verändern
Wir können Indizierung verwenden, um Elemente innerhalb eines Arrays oder einer Schnittstelle zu ändern, indem wir ein nummeriertes Element an einer bestimmten Position auf einen anderen Wert setzen. Dies gibt uns mehr Kontrolle über die Daten in unseren Schnittstellen und Arrays und ermöglicht die programmierte Manipulation von einzelnen Elementen.
Wenn wir den Textwert des Elements an Index 1
des Arrays coral
von "staghorn coral"
auf "foliose coral"
ändern möchten, können wir dies wie folgt vornehmen:
Wenn wir jetzt das Array coral
drucken, wird es anders aussehen:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral"]
Nun, da Sie wissen, wie Sie einzelne Elemente the Arrays oder Schnittstellen verändern können, lassen Sie uns einige Funktionen anschauen, die Ihnen mehr Flexibilität beim Arbeiten mit collectiven Datentypen geben.
Elemente mit len()
zählen
In Go ist len()
eine integrierte Funktion, die dazu gedacht ist, Ihnen beim Arbeiten mit Arrays und Schnittstellen zu helfen. Genau wie mit Strings, können Sie die Länge eines Arrays oder einer Schnittstelle mit len()
berechnen, indem Sie das Array oder die Schnittstelle als Parameter an die Funktion len()
geben.
Zum Beispiel, um herauszufinden, wie viele Elemente im Array coral
sind, würden Sie folgendermaßen verwenden:
Wenn Sie die Länge für das Array coral
ausdrucken, erhalten Sie folgenden Output:
Output4
Dies ergibt die Länge des Arrays 4
im Integer-Datentyp, was richtig ist, weil das Array coral
vier Elemente hat:
Wenn Sie ein Array von Integer mit mehr Elementen erstellen, können Sie dieses auch mit der len()
Funktion verwenden:
Dies würde zu folgender Ausgabe führen:
Output13
Obwohl diese Beispielarrays relativ wenige Elemente haben, ist die len()
Funktion insbesondere bei sehr großen Arrays praktisch, um zu bestimmen wie viele Elemente sie haben.
Nächstens werden wir über die Methode zur Addition eines Elements zu einem Kollektionstyp und zeigen, dass aufgrund der festen Länge von Arrays die Anfügung dieser statischen Datentypen zu einem Fehler führen wird.
Append-Elemente mit append()
append()
ist eine in Go vorbereitete Methode, mit der Elemente zu einer Sammlungsdatatype hinzugefügt werden können. Jedoch funktioniert diese Methode nicht, wenn sie mit einem Array verwendet wird. Als erwähnt wurde, ist das primäre Unterschied zwischen Arrays und Slices, dass die Größe von Arrays nach deren Definition nicht modifiziert werden kann. Dies bedeutet, dass Sie die Werte der Elemente in einem Array ändern können, aber Sie können den Array größer oder kleiner machen, nachdem er definiert worden ist.
Lassen Sie uns nun Ihr coral
-Array betrachten:
Um einen Eintrag "schwarzer Korallen"
zu diesem Array hinzuzufügen, würde Sie mit der append()
-Funktion des Arrays versuchen, indem Sie schreiben:
Sie erhalten dann einen Fehler, da Ihr Output:
Outputfirst argument to append must be slice; have [4]string
Um dies zu korrigieren, lernen wir mehr über den Schnittstellen-Datentyp und wie man einen Schnitt definiert sowie wie man von einem Array in einen Schnitt konvertiert.
Schnitte
Eine Schnitt ist ein Datentyp in Go, der als mutable, also veränderbar, eine bestimmte Reihe von Elementen darstellt. Da die Größe eines Schnitts variabel ist, gibt es viel mehr Flexibilität, wenn Sie mit Datensammlungen arbeiten, die in der Zukunft möglicherweise expandieren oder kontrahieren sollen; bei der Arbeit mit Datenkollektionen, die sich in der Zukunft größer oder kleiner werden können, ist es wahrscheinlich, dass Sie den Schnittdatentyp benötigen. Wenn Sie viele Elemente speichern oder über Elemente iterieren und Sie die Elemente leicht modifizieren möchten, sollten Sie wahrscheinlich mit dem Schnittdatentyp arbeiten. Wenn Sie viel Elemente speichern oder über Elemente iterieren und Sie die Elemente leicht modifizieren müssen, sollten Sie wahrscheinlich mit dem Schnittdatentyp arbeiten.
Definition einer Schnitt
Die Schnitte werden durch die Anmeldung des Datentyps vor einem leeren Satz von Kreuzzeichen ([]
) und einer Liste von Elementen zwischen geschwungenen Klammern ({}
) definiert. Sie merken sich, dass sie im Gegensatz zu Arrays, die einen int
zwischen den Brackets benötigen, um eine bestimmte Länge festlegen, keine zwischen den Brackets stehen, repräsentierend ihre variablen Länge.
Lassen Sie uns ein Slice erstellen, das Elemente vom Typ String enthält:
Wenn Sie diese Slice ausdrucken, können Sie sehen, welche Elemente in der Slice sind:
Dies wird zu folgender Ausgabe führen:
Output["shark" "cuttlefish" "squid" "mantis shrimp" "anemone"]
Wenn Sie eine Slice mit einer bestimmten Länge ohne zuerst die Elemente der Sammlung zu befüllen wollen, können Sie die inbuilt make()
Funktion verwenden:
Wenn Sie diese Slice drucken, erhalten Sie:
Output["" "" ""]
Wenn Sie eine bestimmte Kapazität für eine bestimmte Anzahl an Elementen vorbereiten möchten, können Sie einen dritten Argument make()
übergeben:
Dies macht eine Null-initialisierte Slice mit einer Länge von 3
und einer vorgegebenen Kapazität von 5
Elementen.
Sie haben jetzt die Möglichkeit, wie man eine Slice definiert. Jedoch löst dies noch nicht den Fehler mit dem coral
-Array aus dem letzten Mal. Um die append()
-Funktion mit coral
zu verwenden, mussten Sie zunächst lernen, wie man Teile eines Arrays in Slices schneiden kann.
Schnittieren von Arrays in Slices
Mit Indexnummern können Sie bestimmte Bereiche aus einem Array auswählen. Dies wird als Schnitt des Arrays bezeichnet und Sie können dies machen, indem Sie eine Range von Indexnummern schreiben, getrennt durch einen Doppelpunkt, in der Form von [erster_index:zweiter_index]
. Es ist jedoch wichtig zu beachten, dass bei der Schnittbildung ein Schnitt erstellt wird, nicht ein Array.
Wenn Sie beispielsweise nur die mittleren Elemente des korallen
-Arrays ohne das erste und letzte Element ausgeben möchten, können Sie dies mit einer Schnittoperation machen, die mit dem Schreiben einer Range beginnend ab 1
und vor 3
beginnend erfolgt:
Eine mit diesem Zeilen geschriebene Programmausführung liefert folgendes Ergebnis:
Output[foliose coral pillar coral]
Wenn Sie einen Schnitt erstellen, wie in [1:3]
, dann ist die erste Zahl der Startpunkt (inklusive), und die zweite Zahl ist die Summe der ersten Zahl und der insgesamt gewünschten Anzahl von Elementen:
array[starting_index : (starting_index + length_of_slice)]
So sieht sich die Berechnung wie folgt aus:
array[1 : (1 + 2)]
Dies ist also die Notation:
Wenn du den Anfang oder Ende des Arrays als Startpunkt oder Endpunkt des Schnitts angeben möchtest, kannst du einen der Zahlen im array[erster_index:zweiter_index]
-Syntax omittern. So könnten Sie zum Beispiel die ersten drei Elemente des arrays korallen
ausgeben, indem Sie schreiben:
Dies wird dann folgendes ausgeben:
Output[blue coral foliose coral pillar coral]
Diese Ausgabe zeigt den Anfang des Arrays, unter dem die Index-Nummer 3
liegt.
Um alle Elemente am Ende eines Arrays zu includieren, verwenden Sie das Syntax umgekehrt:
Dies würde folgende Schnittstelle liefern:
Output[foliose coral pillar coral elkhorn coral]
In diesem Abschnitt wurde erklärt, wie Sie einzelne Teile eines Arrays durch Schnitte aus einem Unterbereich abrufen können. In der nächsten Schritte werden Sie lernen, wie Sie ganze Arrays in Schnitte konvertieren.
Aus einem Array in einen Schnitt konvertieren
Wenn Sie eine ArrayListe erstellen und später feststellen, dass Sie sie mit variablen Länge benötigen, können Sie sie in einen Schnitt konvertieren. Um eine ArrayListe in einen Schnitt zu konvertieren, verwenden Sie das Schnittsatzprozess, den Sie im Schritt „Arrays in Schnitte schneiden“ dieser Tutorial gelernt haben, nur diesmal wählen Sie beide Indexnummern aus, die die Endpunkte bestimmten sollen:
Beachten Sie, dass Sie nicht die Variable coral
selbst in einen Schnitt konvertieren können, da einmal definierte Variablen in Go ihre Typen nicht geändert werden können. Um dies zu umgehen, können Sie die gesamten Inhalte der ArrayListe in eine neue Variable als Schnitt konvertieren:
Wenn Sie coralSlice
druckten, bekommen Sie folgendes Ergebnis:
Output[blue coral foliose coral pillar coral elkhorn coral]
Nun versuchen Sie, das black coral
-Element wie im Array-Abschnitt hinzuzufügen, indem Sie append()
mit dem neuen konvertierten Slice verwenden:
Dies wird folgende Ausgabe liefern:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral"]
Wir können auch mehr als ein Element in einer einzigen append()
-Anweisung hinzufügen:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral" "antipathes" "leptopsammia"]
Um zwei Slices zusammenzuführen, kannst du append()
verwenden, aber du musst das zweite Argument, um das hinzuzufügen, mittels der ...
-Erweiterungssyntax ausweiten:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral" "antipathes" "leptopsammia" "massive coral" "soft coral"]
Nachdem du gelernt hast, wie du ein Element zu deinem Slice hinzufügen kannst, werden wir anschließend anschauen, wie du einen entfernen kannst.
Ein Element aus einem Slice entfernen
Im Gegensatz zu anderen Sprachen bietet Go keine integrierten Funktionen an, um ein Element aus einem Slice zu entfernen. Elemente müssen aus einem Slice durch Slicing entfernt werden.
Um ein Element zu entfernen, musst du die Elemente, die vor diesem Element sind, und die Elemente, die danach sind, säubern und diese beiden neuen Slices anschließend zusammenfügen, ohne das Element, das entfernt werden soll.
Wenn i
der Index des zu entfernenden Elements ist, dann hat dieser Prozess die folgende Formatierung:
Von coralSlice
möchten wir das Element "elkhorn coral"
entfernen. Dieses Element befindet sich an der Indexposition 3
.
Output["blue coral" "foliose coral" "pillar coral" "black coral" "antipathes" "leptopsammia" "massive coral" "soft coral"]
Nun enthält der Indexposition 3
kein Element mehr, die Zeichenkette "elkhorn coral"
ist also nicht mehr in unserem Slice coralSlice
enthalten.
Wir können auch eine Bereichsauswahl mit dem selben Ansatz entfernen. So sagen wir uns beispielsweise nicht nur den Eintrag "elkhorn coral"
, sondern auch "black coral"
und "antipathes"
. Wir können diese Elemente mit einem Bereich in der Ausdrucksformel aus der Zeichenfolge entfernen:
Dieser Code wird die Indizes 3
, 4
, und 5
aus der Zeichenfolge entfernen:
Output["blue coral" "foliose coral" "pillar coral" "leptopsammia" "massive coral" "soft coral"]
Nun haben Sie verstanden, wie man Elemente einer Slicing auswählen und entfernen kann. Jetzt schauen wir uns an, wie du die Menge der Daten einer Slice zu jeder Zeit messen kannst.
Die Messung der Kapazität einer Slice mit cap()
Da Slices eine variabile Länge haben, ist die len()
-Methode nicht die beste Option, um die Größe dieses Datentypes zu bestimmen. Stattdessen können Sie die cap()
-Funktion verwenden, um zu erfahren, wie viele Elemente eine Slice aufnehmen kann. Dies wird dir zeigen, wie viel Speicher bereits für diese Slice allokiert wurde.
Hinweis: Da die Länge und Kapazität eines Arrays immer gleich sind, funktioniert die cap()
-Funktion nicht auf Arrays.
Eine gängige Anwendung für die cap()
-Funktion ist das Erstellen einer Slice mit einer festen Anzahl von Elementen und dann programmatisch Elemente hinzufügen, ohne dass es zu unnotigem Speicherallokationen kommt, die über die aktuell zugewiesene Kapazität hinausgehen.
Um eine Liste von Zahlen, 0
bis 3
, zu erstellen können wir entweder einen Loop verwenden und append()
oder zunächst die Slicen vorbereiten und dann mit cap()
durchlaufen, um die Werte zu füllen.
Zunächst schauen wir uns das Beispiel an, in dem wir append()
verwenden:
Output[0 1 2 3]
Im Beispiel haben wir eine Slicen erstellt und dann einen for
-Loop erstellt, der vier Mal iteriert wurde. Jede Iteration hat den aktuellen Wert des Loop-Variablen i
in die Indexe der numbers
-Slicen hinzugefügt. Jedoch könnte dies zu unnötigen Speicherallokationen führen, die deinen Programm langsam machen können. Wenn du eine leere Slice hinzufügst und jedes Mal append()
benutzt, wird das Programm die Kapazität der Slice überprüfen. Wenn die hinzugefügte Elemente diese Kapazität überschreiten, wird das Programm zusätzliche Speicher allokieren, um sie zu decken. Dieser Aufwand kann deinem Programm zu einer langsamer Ausführung führen.
Nun schauen wir uns das Beispiel an, in dem wir die Slice ohne append()
ausfüllen, indem wir eine bestimmte Länge/Kapazität vorbereiten:
Output[0 1 2 3]
Im Beispiel haben wir make()
verwendet, um eine Slice zu erstellen und ihr eine bestimmte Anzahl/Kapazität zu geben. Wir haben dann die cap()
Funktion im Loop verwendet, um jede Nulled Elemente durchlaufen und jede bis sie die vorgegebene Kapazität erreicht hatte, zu füllen. In jeder Iteration haben wir den aktuellen Wert der Loop-Variablen i
in den Index der numbers
-Slice eingetragen.
Während die Funktionen append()
und cap()
funktionell gleichwertig sind, vermeiden die Beispiele für cap()
jegliche zusätzlichen Speicherallokationen, die bei der Verwendung der append()
-Funktion notwendig gewesen wären.
Zusammensetzung von mehrdimensionalen Schnittstellen
Sie können auch Schnittstellen definieren, die aus anderen Schnittstellen bestehen, jede innerhalb der größeren Klammern des übergeordneten Schnittstellen. Solche als mehrdimensionale Schnittstellen bezeichnet werden können, können als Abbildungen multidimensionaler Koordinaten gesehen werden; zum Beispiel können eine Sammlung von fünf Schnittstellen sein, die jeweils sechs Elemente lang sind, um einen zwei-dimensionalen Grid zu reprasentieren mit einer horizontalen Länge von fünf und einer vertikalen Höhe von sechs.
Lassen Sie uns nun das folgende mehrdimensionale Schnittstellenbeispiel untersuchen:
Um ein Element in diesem Schnittstellenkonstrukt zu erreichen, müssen Sie mehrere Indexe verwenden, jeweils für jede Dimension des Konstrukts:
Im vorherigen Code erst identifizieren wir das Element auf Index 0
des Schnittstellen-Elementes auf Index 1
, dann zeigen wir das Element auf Index 0
des Schnittstellen-Elementes auf Index 0
. Dies wird den folgenden Ergebnis liefern:
OutputSammy
shark
Die folgenden sind die Indexwerte für die restlichen einzelnen Elemente:
Wenn Sie mit multidimensionalen Schnitten arbeiten, ist es wichtig zu beachten, dass Sie mehr als einen Indexnummer benötigen, um bestimmte Elemente innerhalb des relevanten eingebetteten Schnittes zu erreichen.
Konklusion
In diesem Tutorial haben Sie die Grundlagen zur Arbeit mit Arrays und Slices in Go kennengelernt. Sie wurden durch mehrere Übungen dazu herangeführt, wie Arrays fest in Länge sind, während Slices variabel in Länge sind, und wie diese Unterschiede den Situationsgebrauch dieser Datenstrukturen beeinflussen.
Um weiterhin Studien über Datenstrukturen in Go zu machen, schauen Sie sich unser Artikel über Die Verwendung von Maps in Go an, oder erkunden Sie die ganze Go-Programmierung lernen-Reihe.
Source:
https://www.digitalocean.com/community/tutorials/understanding-arrays-and-slices-in-go