Vergleich von struct, slice und map in Go: vollständige Analyse

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

Vergleich von struct, slice und map in Go: vom Anfänger zum Profi

\n\n

Haben Sie jemals Go-Code geschrieben, der zwei Strukturen, zwei Slices oder zwei Maps vergleichen sollte, und einen Kompilierungsfehler erhalten: invalid operation: cannot compare? Wenn ja, sind Sie nicht allein. Dies ist eine der häufigsten Fragen auf Stack Overflow (Zehntausende von Aufrufen!), die selbst erfahrene Entwickler, die von anderen Sprachen zu Go gewechselt sind, vor ein Rätsel stellt.

\n\n

In diesem Artikel klären wir ein für alle Mal, wie man zusammengesetzte Datentypen in Go korrekt vergleicht. Sie erfahren, warum == nicht immer funktioniert, wann reflect.DeepEqual verwendet werden sollte und wie Sie Ihre eigene effiziente Vergleichsfunktion schreiben. Los geht's!

\n\n

Warum funktioniert der einfache Vergleich mit == nicht immer?

\n\n

In Go funktioniert der Operator == nur für vergleichbare Typen (comparable). Dazu gehören:

\n\n
    \n
  • Basistypen: int, string, bool, float usw.
  • \n
  • Zeiger (pointer)
  • \n
  • Kanäle (channel)
  • \n
  • Schnittstellen (wenn die dynamischen Typen vergleichbar sind)
  • \n
  • Strukturen, bei denen alle Felder vergleichbar sind
  • \n
  • Arrays (array), wenn das Array-Element vergleichbar ist
  • \n
\n\n

Slices und Maps sind jedoch nicht direkt mit == vergleichbar. Der Versuch führt zu einem Kompilierungsfehler. Warum? Weil ein Slice ein Referenztyp ist, der einen Zeiger auf die Daten, die Länge und die Kapazität enthält. Zwei Slices können inhaltlich "gleich" sein, aber unterschiedliche interne Strukturen haben.

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    a := []int{1, 2, 3}\n    b := []int{1, 2, 3}\n    \n    // Kompilierungsfehler!\n    // fmt.Println(a == b) \n    \n    fmt.Println("Funktioniert nur mit nil:")\n    fmt.Println(a == nil) // false\n    fmt.Println(b == nil) // false\n}
\n\n

Das Gleiche gilt für Maps. Das Einzige, was Sie mit == überprüfen können, ist die Gleichheit mit nil.

\n\n

Vergleich von Strukturen (struct) in Go

\n\n

Der Vergleich von Strukturen ist der tückischste Fall. Wenn alle Felder Ihrer Struktur vergleichbare Typen sind, dann funktioniert == tatsächlich!

\n\n
type Person struct {\n    Name string\n    Age  int\n}\n\nfunc main() {\n    p1 := Person{"Alice", 30}\n    p2 := Person{"Alice", 30}\n    \n    fmt.Println(p1 == p2) // true — funktioniert!\n}
\n\n

Das Problem tritt jedoch auf, wenn die Struktur ein Slice oder eine Map enthält:

\n\n
type PersonWithHobbies struct {\n    Name    string\n    Age     int\n    Hobbies []string  // Slice — kein vergleichbarer Typ\n}\n\nfunc main() {\n    p1 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n    p2 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n    \n    // Kompilierungsfehler!\n    // fmt.Println(p1 == p2)\n}
\n\n

In diesem Fall gibt der Go-Compiler einen Fehler aus: struct containing []string cannot be compared.

\n\n

Lösung Nr. 1: reflect.DeepEqual — universell, aber langsam

\n\n

Der einfachste Weg, beliebige komplexe Typen zu vergleichen, ist die Verwendung der Funktion reflect.DeepEqual aus der Go-Standardbibliothek. Sie durchläuft rekursiv Strukturen, Slices und Maps und vergleicht deren Inhalt.

\n\n
import (\n    "fmt"\n    "reflect"\n)\n\nfunc main() {\n    // Vergleich von Slices\n    a := []int{1, 2, 3}\n    b := []int{1, 2, 3}\n    fmt.Println(reflect.DeepEqual(a, b)) // true\n    \n    // Vergleich von Maps\n    m1 := map[string]int{"a": 1, "b": 2}\n    m2 := map[string]int{"a": 1, "b": 2}\n    fmt.Println(reflect.DeepEqual(m1, m2)) // true\n    \n    // Vergleich von Strukturen mit nicht vergleichbaren Feldern\n    p1 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n    p2 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n    fmt.Println(reflect.DeepEqual(p1, p2)) // true\n}
\n\n

<

Blogs

Buchempfehlungen