Einführung
In diesem Lab wird das Konzept der Generics in Golang vorgestellt. Ab Version 1.18 hat Golang die Unterstützung für Generics hinzugefügt, was es uns ermöglicht, flexibleres und wiederverwendbares Code zu schreiben.
This tutorial is from open-source community. Access the source code
💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken
In diesem Lab wird das Konzept der Generics in Golang vorgestellt. Ab Version 1.18 hat Golang die Unterstützung für Generics hinzugefügt, was es uns ermöglicht, flexibleres und wiederverwendbares Code zu schreiben.
Das Problem, das in diesem Lab gelöst werden soll, ist es, zu verstehen, wie man generische Funktionen und Typen in Golang definiert und verwendet.
$ go run generics.go
keys: [4 1 2]
list: [10 13 23]
Hier ist der vollständige Code:
// Ab Version 1.18 hat Go die Unterstützung für
// _Generics_, auch bekannt als _Typ-Parameter_, hinzugefügt.
package main
import "fmt"
// Als Beispiel für eine generische Funktion nimmt `MapKeys`
// eine Map beliebigen Typs und gibt eine Liste ihrer Schlüssel zurück.
// Diese Funktion hat zwei Typ-Parameter - `K` und `V`;
// `K` hat die _Beschränkung_ `comparable`, was bedeutet, dass
// wir Werte dieses Typs mit den Operatoren `==` und
// `!=` vergleichen können. Dies ist für Map-Schlüssel in Go erforderlich.
// `V` hat die `any`-Beschränkung, was bedeutet, dass es
// auf keiner Weise eingeschränkt ist (`any` ist ein Alias für `interface{}`).
func MapKeys[K comparable, V any](m map[K]V) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// Als Beispiel für einen generischen Typ ist `List` eine
// einfach verkettete Liste mit Werten beliebigen Typs.
type List[T any] struct {
head, tail *element[T]
}
type element[T any] struct {
next *element[T]
val T
}
// Wir können Methoden auf generischen Typen genauso definieren wie
// auf regulären Typen, müssen aber die Typ-Parameter beibehalten.
// Der Typ ist `List[T]`, nicht `List`.
func (lst *List[T]) Push(v T) {
if lst.tail == nil {
lst.head = &element[T]{val: v}
lst.tail = lst.head
} else {
lst.tail.next = &element[T]{val: v}
lst.tail = lst.tail.next
}
}
func (lst *List[T]) GetAll() []T {
var elems []T
for e := lst.head; e!= nil; e = e.next {
elems = append(elems, e.val)
}
return elems
}
func main() {
var m = map[int]string{1: "2", 2: "4", 4: "8"}
// Wenn wir generische Funktionen aufrufen, können wir uns oft auf
// _Typ-Schlussfolgerung_ verlassen. Beachten Sie, dass wir die Typen
// für `K` und `V` nicht angeben müssen, wenn wir
// `MapKeys` aufrufen - der Compiler schließt sie automatisch.
fmt.Println("keys:", MapKeys(m))
//... obwohl wir sie auch explizit angeben könnten.
_ = MapKeys[int, string](m)
lst := List[int]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
fmt.Println("list:", lst.GetAll())
}
Generics sind eine leistungsstarke Funktion, die es uns ermöglicht, flexibleres und wiederverwendbares Code in Golang zu schreiben. Mit Generics können wir Funktionen und Typen definieren, die mit jedem Typ funktionieren, solange sie bestimmte Beschränkungen erfüllen. Indem wir Generics verwenden, können wir Code-Duplizierung reduzieren und die Lesbarkeit und Wartbarkeit des Codes verbessern.