„Wo ist contains?“ – Der erste Schock für Go-Neulinge
\n\nStell dir vor: Du programmierst in Go, hast einen Slice mit Strings ["python", "go", "rust", "javascript"] und willst prüfen, ob "go" darin vorkommt. Wenn du aus Python, Ruby oder JavaScript kommst, tippst du automatisch slice.contains("go") – und bekommst einen roten Kompilierungsfehler. „Was soll das?“ denkst du. „Jede anständige Sammlung hat doch eine contains-Methode!“
Keine Panik. In Go gibt es keine eingebaute contains-Methode für Slices. Das ist kein Bug, sondern ein Feature. Die Sprachentwickler haben entschieden, dass eine universelle Funktion nicht alle Fälle abdeckt (Vergleich von Strings, Zahlen, Strukturen) und überlassen die Implementierung dem Programmierer. Klingt kompliziert, ist aber einfach und elegant. In diesem Artikel zeigen wir dir, wie du contains für einen Slice in Go schreibst, besprechen die Performance, typische Fallstricke und liefern fertige Lösungen.
\n\nWarum hat Go kein contains für Slices?
\nGo ist eine minimalistische Sprache. Es gab keine Generics (vor Version 1.18) und keine Methodenüberladung. Ein Slice ist kein Objekt mit Methoden, sondern eine Datenstruktur: ein Zeiger auf ein Array, Länge und Kapazität. Die Go-Entwickler wollten, dass die contains-Funktion explizit ist, damit der Programmierer immer versteht, wie der Vergleich abläuft. Das reduziert Fehler und macht den Code vorhersagbar.
\nAußerdem ist contains für einen Slice immer eine lineare Suche (O(n)). Wenn du O(1) erwartest, brauchst du eine andere Datenstruktur (z. B. eine Map). Go will diese Komplexität nicht verstecken.
\n\nDer einfachste contains für einen Slice in Go (manuelle Schleife)
\nSchreiben wir einen contains für einen String-Slice. Das ist der Klassiker, den du in jedem Production-Code siehst:
\n\npackage main\n\nimport "fmt"\n\n// Contains prüft, ob ein Element im String-Slice vorhanden ist\nfunc Contains(slice []string, target string) bool {\n for _, item := range slice {\n if item == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n languages := []string{"python", "go", "rust", "javascript"}\n fmt.Println(Contains(languages, "go")) // true\n fmt.Println(Contains(languages, "csharp")) // false\n}\n\nGanz einfach: Wir iterieren über den Slice und vergleichen jedes Element mit dem gesuchten. Gefunden? true, sonst false. Wichtig: Der Operator == funktioniert für Strings, Zahlen, Booleans und Zeiger. Bei Strukturen oder verschachtelten Slices geht das nicht.
Contains für Zahlen
\nFür einen Integer-Slice ist der Code fast identisch:
\n\nfunc ContainsInt(slice []int, target int) bool {\n for _, v := range slice {\n if v == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n numbers := []int{10, 20, 30, 40, 50}\n fmt.Println(ContainsInt(numbers, 30)) // true\n fmt.Println(ContainsInt(numbers, 99)) // false\n}\n\nUnbequem? Ja. Aber das ist Go – Explizitheit und Einfachheit haben Vorrang.
\n\nUniverseller contains für Slices in Go (Generics, Go 1.18+)
\nMit Go 1.18 kamen Generics. Jetzt kannst du eine einzige contains-Funktion für jeden vergleichbaren Typ schreiben:
\n\npackage main\n\nimport "fmt"\n\n// ContainsGeneric funktioniert für jeden comparable Typ\nfunc ContainsGeneric[T comparable](slice []T, target T) bool {\n for _, item := range slice {\n if item == target {\n return true\n }\n }\n return false\n}\n\nfunc main() {\n strs := []string{"a", "b", "c"}\n ints := []int{1, 2, 3}\n floats := []float64{1.1, 2.2, 3.3}\n\n fmt.Println(ContainsGeneric(strs, "b")) // true\n fmt.Println(ContainsGeneric(ints, 5)) // false\n fmt.Println(ContainsGeneric(floats, 2.2)) // true\n}\n\nDie Einschränkung comparable bedeutet, dass der Typ die Operatoren == und != unterstützt.