Generics in Go: vollständiger Leitfaden zu Generics

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

Generics in Go: warum sie nützlich sind und wie man sie verwendet



Mit der Veröffentlichung von Go 1.18 wurde eine der am meisten erwarteten Funktionen in der Sprache eingeführt — Generics (generische Programmierung). Bis zu diesem Zeitpunkt mussten Entwickler entweder Code für verschiedene Datentypen duplizieren oder das leere Interface interface{} mit anschließender Typkonvertierung verwenden. Generics lösen dieses Problem grundlegend. In diesem Artikel werden wir untersuchen, warum sie benötigt werden, wie man sie in der Praxis einsetzt und welche Fallstricke auf Sie warten.



Was sind Generics und warum werden sie in Go benötigt?



Generics (oder generische Typen) ermöglichen es, Funktionen, Strukturen und Methoden zu schreiben, die mit beliebigen Datentypen arbeiten, dabei aber eine strenge Typisierung beibehalten. Das bedeutet, dass Sie eine Funktion schreiben können, die sowohl mit Zahlen als auch mit Strings und benutzerdefinierten Typen arbeitet, ohne die Typinformationen während der Kompilierung zu verlieren.



Vor der Einführung von Generics verwendeten Go-Entwickler hauptsächlich zwei Ansätze:



  • Code-Duplizierung — Schreiben separater Funktionen für int, string, float64 usw.
  • Leeres Interface — Verwendung von interface{} mit anschließendem Type Assertion oder Reflexion, was unsicher und langsam war.


Generics lösen diese Probleme, indem sie das Schreiben von universellem, aber dennoch typsicherem Code ermöglichen. Der Compiler überprüft die Typen während der Kompilierung, was Laufzeitfehler ausschließt.



Syntax von Generics: Typparameter



Die grundlegende Idee von Generics in Go sind Typparameter (type parameters). Sie werden in eckigen Klammern nach dem Funktions- oder Typnamen deklariert.



Betrachten wir ein einfaches Beispiel — eine Funktion, die den kleineren von zwei Werten zurückgibt:



package main

import "fmt"

// Generische Funktion mit Typparameter Tfunc Min[T comparable](a, b T) T { if a < b { return a } return b}

func main() { fmt.Println(Min[int](10, 20)) // 10 fmt.Println(Min[string]("a", "b")) // "a" fmt.Println(Min(3.14, 2.71)) // 2.71 (Typ wird automatisch abgeleitet)}


Hier ist T der Typparameter. comparable ist eine Einschränkung (constraint), die besagt, dass der Typ T Vergleichsoperatoren unterstützen muss. Ohne diese Einschränkung würde der Compiler die Verwendung von < nicht erlauben.



Wichtig: Go kann Typparameter automatisch aus den Argumenten ableiten, daher müssen Sie sie in den meisten Fällen nicht explizit angeben.



Einschränkungen (Constraints) in Go-Generics



Einschränkungen sind ein Schlüsselelement von Generics. Sie legen fest, welche Operationen für die Typparameter zulässig sind. Ohne Einschränkungen weiß der Compiler nicht, welche Methoden oder Operatoren auf T angewendet werden können.



In Go gibt es mehrere eingebaute Einschränkungen:



  • any — ein Synonym für interface{}, erlaubt jeden Typ.
  • comparable — erlaubt Typen, die == und != unterstützen.
  • constraints.Ordered — aus dem Paket golang.org/x/exp/constraints, erlaubt alle geordneten Typen (Zahlen und Strings).


Sie können auch Ihre eigenen Einschränkungen mit Interfaces erstellen:



package main

import "fmt"

// Eigene Einschränkung: Der Typ muss eine Methode String() habentype Stringer interface { String() string}

// Funktion, die mit jedem Stringer arbeitetfunc Print[T Stringer](value T) { fmt.Println(value.String())}

type User struct { Name string}

func (u User) String() string { return "User: " + u.Name}

func main() { user := User{Name: "Alice"} Print(user) // User: Alice}


Beachten Sie: In Go 1.18+ können Interfaces als Einschränkungen verwendet werden, und sie können nicht nur Methoden, sondern auch konkrete

Blogs

Buchempfehlungen