Technologieaustausch

[Go-Serie] Array, Slice und Map

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Verbinden Sie das Vorherige und das Nächste

Wir haben in unserem vorherigen Artikel vorgestellt, dass dies nicht geübt werden sollte.continue Anweisung zur Berechnung der Summe gerader Zahlen innerhalb von 100. Während wir Code schreiben,continueDie Anweisung hilft uns dabei, bestimmte Iterationen zu überspringen, die nicht benötigt werden. In diesem Beispiel werden wir beispielsweise alle ungeraden Zahlen überspringen.

  1. sum := 0
  2. for i := 1; i < 100; i++{
  3. if i & 1 == 0 {
  4. continue
  5. }
  6. sum += i
  7. }
  8. fmt.Println("the sum is",sum)

Beginne zu lernen

Bei der Programmierung müssen wir uns oft mit einer Menge von Elementen desselben Typs befassen, und diese Mengen von Elementen werden durch spezifische Datenstrukturen in der Go-Sprache dargestellt. Heute stelle ich Ihnen verschiedene Sammlungstypen in Go im Detail vor: Array, Slice und Map.

Array

Beginnen wir zunächst mit Arrays. Array ist die grundlegendste Datenstruktur in Go. Es handelt sich um eine Folge fester Länge von Elementen desselben Typs. Sobald ein Array deklariert ist, kann seine Länge nicht mehr geändert werden. Die Deklaration und Initialisierung von Arrays ist sehr einfach.

Array deklarieren

Beim Deklarieren eines Arrays müssen Sie den Array-Typ und die Array-Länge angeben. So wird ein Array deklariert:

var arrayName [arrayLength]elementType

Deklarieren Sie beispielsweise ein ganzzahliges Array der Länge 5:

var numbers [5]int
Array initialisieren

Sie können ein Array auf verschiedene Arten initialisieren:

  • Verwenden Sie die wörtliche Initialisierung:
var numbers = [5]int{1, 2, 3, 4, 5}
  • verwenden:=Kurzes Statement:
numbers := [5]int{1, 2, 3, 4, 5}
  • Array-Länge automatisch ableiten:
numbers := [...]int{1, 2, 3, 4, 5}
  • Geben Sie die Indexinitialisierung an:
numbers := [5]int{0: 1, 4: 5}

Eigenschaften von Arrays

  • Feste Länge: Die Länge des Arrays wird bei der Deklaration festgelegt und kann später nicht mehr geändert werden.
  • Elemente des gleichen Typs: Arrays können nur Elemente desselben Typs enthalten.
  • Speicherzuordnung zusammenhängend: Array-Elemente werden zusammenhängend im Speicher zugewiesen, was den Zugriff auf Array-Elemente sehr effizient macht.

Auf Array-Elemente zugreifen

Sie können über den Index beginnend bei 0 auf Elemente in einem Array zugreifen:

value := numbers[2] // 获取索引为 2 的元素

Array durchqueren

Sie können verwendenforDurchlaufen Sie alle Elemente in einem Array:

  1. for i, value := range numbers {
  2. fmt.Printf("Index: %d, Value: %dn", i, value)
  3. }

Länge des Arrays

Sie können das integrierte verwendenlenFunktion zum Ermitteln der Länge eines Arrays:

length := len(numbers)

Nullwert des Arrays

Wenn ein Array nicht explizit initialisiert wird, werden seine Elemente automatisch auf den Nullwert ihres Typs gesetzt. Der Nullwert eines Integer-Arrays ist beispielsweise 0:

var numbers [5]int // 所有元素都是 0

Mehrdimensionale Arrays

Die Go-Sprache unterstützt auch mehrdimensionale Arrays. Das Folgende ist ein Beispiel für die Deklaration und Initialisierung eines 2x3-Integer-Arrays:

  1. var matrix [2][3]int
  2. matrix = [2][3]int{{1, 2, 3}, {4, 5, 6}}

Einschränkungen von Arrays

Da die Länge des Arrays fest ist, ist dies in manchen Fällen möglicherweise nicht sehr flexibel. Wenn Sie eine Sammlung variabler Länge benötigen, können Sie Slices verwenden.

Scheibe

Als nächstes kommt Slice, ein flexiblerer integrierter Typ, der als dynamisches Array betrachtet werden kann. Die Länge des Slice ist variabel und wird basierend auf einem Array erstellt, was mehr Komfort bietet. So deklarieren und initialisieren Sie ein Slice:

  1. s := make([]int, 3) // 创建一个长度为3的整型切片
  2. s[0] = 1 // 切片元素赋值
  3. s[1] = 2
  4. s[2] = 3
  5. s = append(s, 4) // 向切片追加元素

Obwohl sowohl Arrays als auch Slices in der Go-Sprache zum Speichern einer Reihe von Elementen desselben Typs verwendet werden, weisen sie erhebliche Unterschiede in der Speicherzuweisung, Größenvariabilität und Verwendung auf. Hier sind die Hauptunterschiede zwischen Arrays und Slices:

Größenvariabilität

  • Array : Die Größe eines Arrays wird bei der Deklaration festgelegt und kann später nicht mehr geändert werden.Die Größe eines Arrays ist also Teil seines Typs[3]intUnd[4]intsind verschiedene Typen.
  • Scheibe : Slices sind dynamisch und können zur Laufzeit wachsen oder schrumpfen.Die Größe eines Slice ist also nicht Teil seines Typs[]intIst der gemeinsame Typ für alle ganzzahligen Slices.

Speicherzuweisung

  • Array : Arrays sind Werttypen, und wenn ein Array als Funktionsparameter übergeben wird, wird eine Kopie seines Werts übergeben. Dies bedeutet, dass Änderungen am Array innerhalb der Funktion keinen Einfluss auf das ursprüngliche Array haben.
  • Scheibe : Slice ist ein Referenztyp, der einen Zeiger auf das zugrunde liegende Array sowie die Länge und Kapazität des Slice enthält. Wenn ein Slice als Funktionsparameter übergeben wird, wird eine Kopie des Zeigers übergeben, sodass sich Änderungen am Slice innerhalb der Funktion auf das ursprüngliche Slice auswirken.

Initialisierung

  • Array: Bei der Initialisierung eines Arrays muss dessen Größe angegeben werden und Elementwerte können sofort zugewiesen werden.
  • Scheibe: Slices können durch Literale übergeben werden,makeFunktion oder Slice aus einem Array zur Initialisierung, keine Größe angegeben.

Beispielcode

Hier sind Beispiele für die Initialisierung von Arrays und Slices:

  1. // 数组
  2. var arr [3]int = [3]int{1, 2, 3}
  3. // 切片
  4. var slice []int = []int{1, 2, 3}
  5. // 或者使用 make 函数
  6. slice := make([]int, 3)

Funktionelle Unterschiede

  • Array: Da die Größe fest ist, ist die Größe des Arrays zur Kompilierungszeit bekannt, was es ermöglicht, Speicher für das Array auf dem Stapel zuzuweisen, und die zeitliche Komplexität des Zugriffs auf die Array-Elemente beträgt O(1).
  • Scheibe: Slicing bietet mehr Flexibilität durchappend Die Funktion fügt Elemente hinzu oder erhält Unterabschnitte durch Slicing-Vorgänge.Das zugrunde liegende Array des Slice kann auf dem Heap zugewiesen werden, und die zeitliche Komplexität des Zugriffs auf die Slice-Elemente beträgt ebenfalls O(1), aberappendKann zu einer Neuzuweisung des zugrunde liegenden Arrays führen, bei der es sich normalerweise um eine O(n)-Operation handelt.

Kartierung

Schauen wir uns zum Schluss noch das Mapping an. Eine Karte ist ein assoziatives Array in Go, das Schlüssel Werten zuordnet. Die Schlüssel der Karte können von jedem Typ sein, der vom Gleichheitsoperator unterstützt wird, z. B. Ganzzahlen, Gleitkommazahlen, Zeichenfolgen, Zeiger, Schnittstellen (sofern die in der Schnittstelle enthaltenen Werte vergleichbar sind), Strukturen und Arrays. Der zugeordnete Wert kann einen beliebigen Typ haben.

Deklaration und Initialisierung

Karte deklarieren

Die Syntax zum Deklarieren einer Karte lautet wie folgt:

var mapName map[keyType]valueType

Deklarieren Sie beispielsweise eine Karte mit Schlüsseln als Zeichenfolgen und Werten als Ganzzahlen:

var scores map[string]int
Karte initialisieren

Nachdem Sie die Karte deklariert haben, müssen Sie bestehenmakeFunktion, um es zu initialisieren, damit es verwendet werden kann:

scores = make(map[string]int)

Alternativ können Sie eine kurze Deklaration verwenden und Folgendes initialisieren:

scores := make(map[string]int)

Sie können zum Zeitpunkt der Deklaration auch Literale zur Initialisierung verwenden:

  1. scores := map[string]int{
  2. "alice": 90,
  3. "bob": 85,
  4. "charlie": 88,
  5. }

Merkmale der Karte

  • entscheidende Einzigartigkeit: In einer Karte ist jeder Schlüssel eindeutig. Wenn Sie versuchen, einen vorhandenen Schlüssel einzufügen, wird der dem Schlüssel entsprechende Wert aktualisiert.
  • Störung:map ist ungeordnet und die Reihenfolge der Elemente kann bei jeder Iteration der Karte unterschiedlich sein.
  • dynamische Größe:Die Größe der Karte ist dynamisch. Sie können nach Bedarf Schlüssel-Wert-Paare hinzufügen oder entfernen.
  • Referenztyp: Map ist ein Referenztyp. Wenn Sie Map an eine Funktion übergeben, übergeben Sie tatsächlich einen Zeiger auf die zugrunde liegende Datenstruktur.

Einsatzkarte

Element hinzufügen
scores["alice"] = 90
Element abrufen
value := scores["alice"]

Wenn der Schlüssel nicht vorhanden ist, wird ein Nullwert für diesen Werttyp zurückgegeben.

Überprüfen Sie, ob der Schlüssel vorhanden ist

Mit dem Idiom „comma -ok“ können Sie überprüfen, ob der Schlüssel in der Karte vorhanden ist:

  1. value, exists := scores["alice"]
  2. if exists {
  3. // 键存在
  4. } else {
  5. // 键不存在
  6. }
Element löschen

verwendendeleteDie Funktion kann ein Schlüssel-Wert-Paar aus der Karte entfernen:

delete(scores, "alice")

Wenn der Schlüssel nicht existiert,deleteDie Funktion macht nichts.

Durchquere die Karte

verwendenforEine Schleife kann alle Schlüssel-Wert-Paare in der Karte durchlaufen:

  1. for key, value := range scores {
  2. fmt.Printf("%s: %dn", key, value)
  3. }

Nullwert der Karte

Der Nullwert der Karte istnil .einsnil Eine Karte hat keine zugrunde liegende Datenstruktur und kann keine Elemente hinzufügen.Bevor Sie Elemente zur Karte hinzufügen, müssen Sie diese verwendenmakeInitialisieren Sie es.

Länge der Karte

Sie können das integrierte verwendenlenFunktion zum Abrufen der Anzahl der Schlüssel-Wert-Paare in der Karte:

length := len(scores)

Kartenschlüsseltyp

Die Schlüssel der Karte können von jedem vergleichbaren Typ sein, z. B. Ganzzahlen, Gleitkommazahlen, Zeichenfolgen, Zeiger, Schnittstellen (sofern die in der Schnittstelle enthaltenen Werte vergleichbar sind), Strukturen, Arrays usw. Slices, Maps und Funktionen können nicht als Map-Schlüssel verwendet werden, da diese Typen keine Gleichheitsvergleiche unterstützen.

Es ist leicht, Fehler zu machen

In der Go-Sprache sind Arrays, Slices und Maps drei häufig verwendete Datenstrukturen, die jeweils unterschiedliche Eigenschaften und Überlegungen aufweisen. Bei der Verwendung sind folgende Punkte zu beachten:

Array

  • Vermeiden Sie die Verwendung zu großer Arrays, da diese viel Stapelplatz beanspruchen und zu einem Stapelüberlauf führen können.
  • Arrays werden verwendet, wenn eine Datensammlung mit fester Größe erforderlich ist.

Scheibe

  • Wenn das Slicing erweitert wird, kann es zu einer Neuzuweisung von Speicher kommen. Versuchen Sie, ausreichend Kapazität vorab zuzuweisen, um eine häufige Erweiterung zu vermeiden.
  • Vermeiden Sie die Verwendung zu großer Slices, da diese viel Heap-Speicherplatz beanspruchen können.
  • Beachten Sie, dass der Nullwert des Slice istnil, muss vor der Verwendung initialisiert werden.

Karte

  • Der Nullwert der Karte istnilnilMap kann nicht zum Speichern von Schlüssel-Wert-Paaren verwendet werden und muss vor der Verwendung initialisiert werden.
  • In einer gleichzeitigen Umgebung sind Lese- und Schreibvorgänge auf der Karte nicht threadsicher und müssen durch die Verwendung von Mutex-Sperren oder anderen Synchronisierungsmechanismen geschützt werden.
  • verwendendeleteDas Löschen eines nicht vorhandenen Schlüssels erzeugt keinen Fehler, es kann jedoch sicher überprüft werden, ob der Schlüssel vorhanden ist.