Konstante Arrays in Go: Wie man sie deklariert und nicht verrückt wird

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Die ewige Frage von Stack Overflow

\n\n

Wenn Sie jemals "Declare a constant array in Go" gegoogelt haben, haben Sie sicherlich genau das Thema auf Stack Overflow mit Tausenden von Aufrufen gesehen. Und ja, Sie sind mit Ihrer Verwirrung nicht allein. In Go kann man tatsächlich nicht einfach const arr = [...]int{1, 2, 3} schreiben – der Compiler wird Ihnen ein höfliches "Nein" sagen.

\n\n

Warum ist das so? Und wie geht man dann vor, wenn wir eine unveränderliche Datenliste benötigen? In diesem Artikel werden wir uns mit der Natur von Konstanten in Go befassen, herausfinden, warum Arrays keine Konstanten sein können, und die besten Umgehungsmöglichkeiten finden. Spoiler: Es gibt eine Lösung, und sie ist sogar schöner, als Sie denken.

\n\n

Warum erlaubt Go keine Deklaration eines konstanten Arrays?

\n\n

Um das zu verstehen, müssen wir unter die Motorhaube der Sprache schauen. In Go sind Konstanten unveränderliche Werte, die zur Kompilierzeit berechnet werden. Sie müssen streng typisiert und vor dem Start des Programms bekannt sein. Arrays hingegen sind zusammengesetzte Datentypen, die Speicher belegen und geändert werden können.

\n\n

Hier ist ein einfaches Beispiel, das NICHT kompiliert wird:

\n\n
package main\n\nconst arr = [3]int{1, 2, 3} // Fehler: const initializer [3]int{1, 2, 3} is not a constant\n\nfunc main() {\n    fmt.Println(arr)\n}
\n\n

Der Compiler sagt: "Hey, das ist keine Konstante!". Und er hat recht. Selbst wenn das Array als const deklariert ist, garantiert Go nicht, dass sein Inhalt nicht über Zeiger oder Slices geändert wird. Daher haben die Sprachentwickler entschieden: keine konstanten Arrays.

\n\n

Aber keine Sorge. Es gibt mindestens drei Möglichkeiten, diese Einschränkung zu umgehen, und jede hat ihre Vorteile.

\n\n

Methode 1: Verwenden einer Variable mit dem Kommentar "nicht anfassen"

\n\n

Der einfachste und naivste Weg ist, einfach eine Variable zu deklarieren und zu hoffen, dass niemand sie ändert. Aber wir sind doch ernsthafte Entwickler, oder?

\n\n
package main\n\nimport "fmt"\n\n// arr - konstantes Array. Bitte ändern Sie es nicht.\nvar arr = [3]int{1, 2, 3}\n\nfunc main() {\n    fmt.Println(arr)\n    // arr[0] = 100 // Kommentieren Sie dies aus – und alles wird kaputtgehen\n}
\n\n

Die Nachteile liegen auf der Hand: Es ist keine echte Konstante. Jeder kann das Array durch Zuweisung ändern. Aber für schnelle Prototypen oder kleine Projekte reicht es.

\n\n

Methode 2: Getter-Funktion (der richtige Weg)

\n\n

Dieser Ansatz wird in Produktionscode verwendet. Wir verstecken das Array innerhalb einer Funktion und geben eine Kopie davon zurück. So kann niemand das Original ändern.

\n\n
package main\n\nimport "fmt"\n\n// getColors gibt eine Kopie des Farb-Arrays zurück.\n// Das Array ist vor Änderungen von außen geschützt.\nfunc getColors() [3]string {\n    return [3]string{"Red", "Green", "Blue"}\n}\n\nfunc main() {\n    colors := getColors()\n    fmt.Println(colors)\n    // colors[0] = "Yellow" // Dies ändert die Kopie, nicht das Original\n}
\n\n

Warum ist das gut? Weil:

\n
    \n
  • Das Array kann nicht von außen geändert werden – die Funktion gibt eine Kopie zurück.
  • \n
  • Der Code ist lesbar und verständlich.
  • \n
  • Einfach zu testen und zu warten.
  • \n
\n\n

Es gibt jedoch einen Haken: Jeder Aufruf der Funktion erstellt eine neue Kopie des Arrays. Wenn das Array groß ist (z. B. 1000 Elemente), kann dies aufwändig sein. Verwenden Sie in diesem Fall die folgende Methode.

\n\n

Methode 3: Paketvariable mit privatem Zugriff

\n\n

Wenn Sie ein Paket schreiben und das Array vor Änderungen schützen möchten, machen Sie es nicht exportierbar (mit Kleinbuchstaben) und gewähren Sie den Zugriff über eine Funktion.

\n\n
package constants\n\n// Das Array ist nur innerhalb des Pakets zugänglich\nvar defaultPorts = [5]int{80, 443, 8080, 3000, 5000}\n\n// GetDefaultPorts gibt eine Kopie des Port-Arrays zurück.\nfunc GetDefaultPorts() [5]int {\n    return defaultPorts\n}
\n\n

Jetzt können die Benutzer Ihres Pakets die Daten nur lesen, aber nicht ändern. Ideal für Bibliotheken.

\n\n

Methode 4: Verwendung von iota für konstante Sätze

\n\n

Was ist, wenn Sie nicht die Werte selbst, sondern deren Indizes benötigen? Zum Bei

Blogs

Buchempfehlungen