Slices, Maps, Structs und geteilter Speicher
Kapitel 3
Themen: Arrays, Slices, Maps, Structs.
Arrays
In Go ist die Größe Teil des Typs. [3]int und [4]int sind verschiedene Typen. Eine Funktion, die [3]int akzeptiert, akzeptiert kein [4]int.
var x [3]int
var y [4]int
x = y // Compile-Fehler
Arrays werden im Alltag selten direkt verwendet. Sie dienen als Backing-Storage für Slices.
Slices
Slices werden ohne Größe im Typ deklariert.
x := []int{10, 20, 30}
Drei interne Werte: Länge, Kapazität, Pointer auf das Backing-Array.
append gibt ein neues Slice zurück
var x []int
x = append(x, 10)
Das Ergebnis muss zugewiesen werden. Go ist call-by-value: append bekommt eine Kopie des Slice-Headers, hängt an und gibt die neue Version zurück.
Länge gegen Kapazität
Länge ist die Anzahl belegter Elemente. Kapazität ist die Größe des reservierten Backing-Arrays.
x := make([]int, 0, 10) // Länge 0, Kapazität 10
x = append(x, 1, 2, 3) // Länge 3, Kapazität 10
Geht ein append über die Kapazität hinaus, alloziert Go ein neues, größeres Backing-Array und kopiert um. Vorab-Allokation mit make reduziert Allokationen und GC-Druck.
Slicing teilt Speicher
x := []string{"a", "b", "c", "d"}
y := x[:2] // y = ["a", "b"]
x[1] = "z"
fmt.Println(y) // ["a", "z"]
Slicing kopiert nicht. Beide Variablen zeigen auf dasselbe Backing-Array.
Mit dem dreiteiligen Ausdruck lässt sich die Kapazität deckeln, sodass ein späteres append ein neues Array alloziert.
y := x[:2:2] // Kapazität bei 2 gedeckelt
Maps
teams := map[string]int{
"Orcas": 1,
"Lions": 2,
}
Wichtige Eigenschaften:
- Zero-Wert ist
nil. Lesen aus einer nil-Map gibt den Zero-Wert des Wertetyps. Schreiben in eine nil-Map ist ein Panic. - Maps lassen sich nicht mit
==vergleichen. - Keys müssen vergleichbar sein. Slices und Maps sind nicht als Key erlaubt.
Komma-ok-Idiom
Ein fehlender Key liefert den Zero-Wert ohne Fehler. Um fehlenden Key von echtem Zero-Wert zu unterscheiden, gibt es die Komma-ok-Form.
v, ok := m["key"]
if ok {
// Key existiert, v hat den Wert
}
Map als Set
Go hat keinen eingebauten Set-Typ. Üblich ist map[T]bool oder map[T]struct{} für minimalen Speicherverbrauch.
intSet := map[int]bool{}
intSet[5] = true
if intSet[5] {
fmt.Println("5 ist im Set")
}
Structs
Zum Gruppieren zusammengehöriger Felder.
type Person struct {
Name string
Age int
Pet string
}
Eigenschaften:
- Struct-Literale können Feldnamen verwenden (empfohlen) oder positional sein.
- Structs sind mit
==vergleichbar, wenn alle Felder vergleichbar sind. - Anonyme Structs sind möglich, etwa für einmalige Shapes in Tests.
Go kennt keine Klassen und keine Vererbung. Structs mit Methoden ersetzen diese Konzepte.
Zusammenfassung
- Arrays existieren, werden im Alltag kaum verwendet
appendgibt ein neues Slice zurück, immer wieder zuweisen- Länge und Kapazität sind zwei verschiedene Werte
- Slicing teilt Speicher, dreiteiliger Ausdruck deckelt die Kapazität
- Komma-ok-Idiom unterscheidet fehlenden Key von Zero-Wert
- Structs gruppieren Daten, keine Vererbung