Heim > Backend-Entwicklung > Golang > Go's Generics: Intelligenteren Code schreiben, der mit mehreren Typen funktioniert

Go's Generics: Intelligenteren Code schreiben, der mit mehreren Typen funktioniert

Patricia Arquette
Freigeben: 2024-11-28 22:40:11
Original
320 Leute haben es durchsucht

Go s Generics: Writing Smarter Code That Works with Multiple Types

Generika kommen zum Mitnehmen, und das ist eine große Sache. Ich habe mich mit den vorgeschlagenen Änderungen für Go 2 befasst und freue mich, Ihnen mitteilen zu können, was ich über diese leistungsstarke neue Funktion gelernt habe.

Generika ermöglichen es uns im Kern, Code zu schreiben, der mit mehreren Typen funktioniert. Anstatt separate Funktionen für Ints, Strings und benutzerdefinierte Typen zu schreiben, können wir eine einzige generische Funktion schreiben, die sie alle verarbeitet. Dies führt zu flexiblerem und wiederverwendbarerem Code.

Beginnen wir mit einem einfachen Beispiel. So könnten wir eine generische „Max“-Funktion schreiben:

func Max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}
Nach dem Login kopieren
Nach dem Login kopieren

Diese Funktion funktioniert mit jedem Typ T, der die Ordered-Einschränkung erfüllt. Wir können es mit Ints, Floats, Strings oder jedem benutzerdefinierten Typ verwenden, der Vergleichsoperatoren implementiert.

Typbeschränkungen sind ein entscheidender Teil der generischen Implementierung von Go. Sie ermöglichen es uns, anzugeben, welche Operationen unsere generischen Typen unterstützen müssen. Das Constraints-Paket bietet mehrere vordefinierte Einschränkungen, wir können aber auch eigene erstellen.

Zum Beispiel könnten wir eine Einschränkung für Typen definieren, die in Strings konvertiert werden können:

type Stringer interface {
    String() string
}
Nach dem Login kopieren
Nach dem Login kopieren

Jetzt können wir Funktionen schreiben, die mit jedem Typ funktionieren, der in einen String konvertiert werden kann:

func PrintAnything[T Stringer](value T) {
    fmt.Println(value.String())
}
Nach dem Login kopieren

Eines der coolen Dinge an den Generika von Go ist die Typinferenz. In vielen Fällen müssen wir die Typparameter beim Aufruf einer generischen Funktion nicht explizit angeben. Der Compiler kann es herausfinden:

result := Max(5, 10) // Type inferred as int
Nach dem Login kopieren

Dadurch bleibt unser Code sauber und lesbar und bietet gleichzeitig die Vorteile von Generika.

Lassen Sie uns in ein fortgeschritteneres Gebiet vordringen. Mit Typparameterlisten können wir Beziehungen zwischen mehreren Typparametern angeben. Hier ist ein Beispiel für eine Funktion, die zwischen zwei Typen konvertiert:

func Convert[From, To any](value From, converter func(From) To) To {
    return converter(value)
}
Nach dem Login kopieren

Diese Funktion nimmt einen Wert eines beliebigen Typs an, eine Konverterfunktion, und gibt den konvertierten Wert zurück. Es ist unglaublich flexibel und kann in vielen verschiedenen Szenarien eingesetzt werden.

Generika glänzen wirklich, wenn es um Datenstrukturen geht. Lassen Sie uns einen einfachen generischen Stack implementieren:

type Stack[T any] struct {
    items []T
}

func (s *Stack[T]) Push(item T) {
    s.items = append(s.items, item)
}

func (s *Stack[T]) Pop() (T, bool) {
    if len(s.items) == 0 {
        var zero T
        return zero, false
    }
    item := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return item, true
}
Nach dem Login kopieren

Dieser Stapel kann jede Art von Gegenstand aufnehmen. Wir können Stapel von Ints, Strings oder benutzerdefinierten Strukturen erstellen, alle mit demselben Code.

Generika eröffnen auch neue Möglichkeiten für Designmuster in Go. Beispielsweise können wir ein generisches Beobachtermuster implementieren:

type Observable[T any] struct {
    observers []func(T)
}

func (o *Observable[T]) Subscribe(f func(T)) {
    o.observers = append(o.observers, f)
}

func (o *Observable[T]) Notify(data T) {
    for _, f := range o.observers {
        f(data)
    }
}
Nach dem Login kopieren

Dadurch können wir beobachtbare Objekte für jede Art von Daten erstellen und so ereignisgesteuerte Architekturen einfach implementieren.

Beim Refactoring von vorhandenem Go-Code zur Verwendung von Generika ist es wichtig, ein Gleichgewicht zu finden. Während Generika unseren Code flexibler und wiederverwendbarer machen können, können sie ihn auch komplexer und schwerer verständlich machen. Ich habe festgestellt, dass es oft am besten ist, mit konkreten Implementierungen zu beginnen und Generika nur dann einzuführen, wenn wir klare Wiederholungsmuster erkennen.

Wenn wir beispielsweise ähnliche Funktionen für verschiedene Typen schreiben, ist das ein guter Kandidat für die Generierung. Wenn eine Funktion jedoch nur mit einem Typ verwendet wird, ist es wahrscheinlich am besten, sie unverändert zu lassen.

Ein Bereich, in dem Generika wirklich glänzen, ist die Implementierung von Algorithmen. Schauen wir uns eine generische Quicksort-Implementierung an:

func Max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}
Nach dem Login kopieren
Nach dem Login kopieren

Diese Funktion kann Slices jeder geordneten Art sortieren. Wir können es verwenden, um Ints, Floats, Strings oder jeden benutzerdefinierten Typ zu sortieren, der Vergleichsoperatoren implementiert.

Bei der Arbeit mit Generika in Großprojekten ist es wichtig, über die Kompromisse zwischen Flexibilität und Typprüfung zur Kompilierungszeit nachzudenken. Während Generics es uns ermöglichen, flexibleren Code zu schreiben, können sie es auch einfacher machen, Laufzeitfehler einzuführen, wenn wir nicht aufpassen.

Eine Strategie, die ich als nützlich empfunden habe, besteht darin, Generika für internen Bibliothekscode zu verwenden, aber konkrete Typen in öffentlichen APIs verfügbar zu machen. Dadurch profitieren wir von den Vorteilen der internen Code-Wiederverwendung und bieten den Benutzern unserer Bibliothek dennoch eine klare, typsichere Schnittstelle.

Ein weiterer wichtiger Gesichtspunkt ist die Leistung. Obwohl die Implementierung von Generika in Go auf Effizienz ausgelegt ist, kann es im Vergleich zu konkreten Typen dennoch zu einem gewissen Laufzeitaufwand kommen. Bei leistungskritischem Code könnte es sich lohnen, generische und nicht generische Implementierungen zu vergleichen, um festzustellen, ob es einen signifikanten Unterschied gibt.

Generika eröffnen auch neue Möglichkeiten für die Metaprogrammierung in Go. Wir können Funktionen schreiben, die mit Typen selbst und nicht mit Werten arbeiten. Wir könnten zum Beispiel eine Funktion schreiben, die zur Laufzeit einen neuen Strukturtyp generiert:

type Stringer interface {
    String() string
}
Nach dem Login kopieren
Nach dem Login kopieren

Diese Funktion erstellt einen neuen Strukturtyp mit Feldern vom Typ T. Es ist ein leistungsstarkes Werkzeug zum Erstellen dynamischer Datenstrukturen zur Laufzeit.

Abschließend ist es erwähnenswert, dass Generika zwar eine leistungsstarke Funktion, aber nicht immer die beste Lösung sind. Manchmal sind einfache Schnittstellen oder konkrete Typen besser geeignet. Der Schlüssel liegt darin, Generika mit Bedacht einzusetzen, da sie klare Vorteile in Bezug auf die Wiederverwendung von Code und die Typsicherheit bieten.

Generika in Go 2 stellen eine bedeutende Weiterentwicklung der Sprache dar. Sie stellen neue Tools zum Schreiben flexiblen, wiederverwendbaren Codes bereit und behalten gleichzeitig den Schwerpunkt von Go auf Einfachheit und Lesbarkeit bei. Während wir diese Funktion weiterhin erforschen und damit experimentieren, bin ich gespannt, wie sie die Zukunft der Go-Programmierung prägen wird.


Unsere Kreationen

Schauen Sie sich unbedingt unsere Kreationen an:

Investor Central | Intelligentes Leben | Epochen & Echos | Rätselhafte Geheimnisse | Hindutva | Elite-Entwickler | JS-Schulen


Wir sind auf Medium

Tech Koala Insights | Epochs & Echoes World | Investor Central Medium | Puzzling Mysteries Medium | Wissenschaft & Epochen Medium | Modernes Hindutva

Das obige ist der detaillierte Inhalt vonGo's Generics: Intelligenteren Code schreiben, der mit mehreren Typen funktioniert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage