Wie füllt man einen Abschnitt mit konkreten Implementierungen mithilfe von Golang-Generika und -Schnittstellen?

Mary-Kate Olsen
Freigeben: 2024-10-26 10:33:02
Original
712 Leute haben es durchsucht

How to Fill a Slice with Concrete Implementations Using Golang Generics and Interfaces?

Golang-Generika: Schnittstellen und konkrete Implementierungen kombinieren

In Go 1.18 ermöglichen Generika Entwicklern die Definition von Funktionen und Datenstrukturen, die auf einer breiteren Palette von Typen funktionieren. Es ist jedoch ein bestimmtes Szenario aufgetaucht, in dem Benutzer Generika mit Schnittstellen verwenden und gleichzeitig einen konkreten Typ für generische Typparameter bereitstellen möchten.

Problem

Betrachten Sie die folgende Funktion, die darauf abzielt, einen Slice mit zu füllen neue Instanzen eines konkreten Typs:

<code class="go">func Fill[X any](slice []*X) {
   for i := range slice {
      slice[i] = new(X)
   }
}</code>
Nach dem Login kopieren

Diese Funktion funktioniert wie erwartet, wenn ein Teil von Zeigern auf einen bestimmten Typ gefüllt wird, z. B. []*int. Wenn das Slice jedoch aus Schnittstellen besteht und die Funktion mit einem konkreten Typ für den generischen Parameter aufgerufen wird, schlägt die Kompilierung fehl.

<code class="go">xs := make([]sync.Locker, 10) // fill with nils
Fill[sync.Locker,sync.Mutex](xs) // ouch</code>
Nach dem Login kopieren

Ursache

Das Problem entsteht, weil beide Typparameter X eingeschränkt werden und Y zu any entfernt die Beziehung zwischen der Schnittstelle und ihrer konkreten Implementierung. Zur Kompilierungszeit ist nur bekannt, dass X und Y unterschiedliche Typen sind.

Lösung

Um dieses Problem anzugehen, kann eine explizite Behauptung verwendet werden:

<code class="go">func Fill[X, Y any](slice []X) {
    for i := range slice {
        slice[i] = any(*new(Y)).(X)
    }
}</code>
Nach dem Login kopieren

Diese Lösung führt jedoch zu potenziellen Laufzeitpaniken, wenn Y X nicht implementiert. Wenn Y außerdem ein Zeigertyp ist, gehen die Basistypinformationen verloren, was zu Nullwerten anstelle von Instanzen des gewünschten konkreten Typs führt.

Ein besserer Ansatz besteht darin, eine Konstruktorfunktion anstelle eines zweiten generischen Parameters zu verwenden, wie unten gezeigt:

<code class="go">func main() {
    xs := make([]sync.Locker, 10)
    Fill(xs, func() sync.Locker { return &sync.Mutex{} })
}

func Fill[X any](slice []X, f func() X) {
    for i := range slice {
        slice[i] = f()
    }
}</code>
Nach dem Login kopieren

Diese Lösung bietet eine robustere und idiomatischere Möglichkeit, ein Slice mit Instanzen eines bestimmten konkreten Typs zu füllen Aufrechterhaltung der Typensicherheit.

Das obige ist der detaillierte Inhalt vonWie füllt man einen Abschnitt mit konkreten Implementierungen mithilfe von Golang-Generika und -Schnittstellen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
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
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!