Generische Füllfunktion für Slices von Schnittstellen und konkreten Typen
In Golang ist es möglich, generische Funktionen mithilfe von Generics zu definieren. Beim Umgang mit Schnittstellen-Slices und konkreten Typen besteht eine häufige Aufgabe darin, alle Elemente des Slice mit einem konkreten Typ zu initialisieren. Betrachten Sie die folgende Funktion, die darauf abzielt, ein Segment von Zeigern auf einen Typ X mit neuen Instanzen von X zu füllen:
<code class="go">func Fill[X any](slice []*X){ for i := range slice { slice[i] = new(X) } }</code>
Diese Funktion funktioniert wie erwartet für Slices jeden Typs. Es treten jedoch Herausforderungen auf, wenn versucht wird, dieses Verhalten auf Schnittstellensegmente auszudehnen und einen konkreten Typ für das Element (Y) anzugeben.
<code class="go">func Fill[X, Y any](slice []X){ for i := range slice { slice[i] = new(Y) // not work! } }</code>
Wenn sowohl X als auch Y auf „beliebig“ beschränkt werden, ändert sich die Beziehung zwischen Schnittstellen und Implementierern ist verloren. Der Compiler behandelt X und Y als separate Typen und verhindert so Zuweisungen zwischen ihnen innerhalb des Funktionskörpers.
Um dieses Problem zu lösen, 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>
Dieser Ansatz kann jedoch Panik, wenn Y X nicht implementiert, wie im Fall von sync.Mutex (ein Zeigertyp), der sync.Locker implementiert. Da außerdem der Nullwert für einen Zeigertyp Null ist, bietet diese Methode keine wesentliche Verbesserung gegenüber der Verwendung von make([]X, n), das das Slice ebenfalls mit Nullwerten initialisiert.
Eine effektivere Lösung besteht darin, eine Konstruktorfunktion anstelle eines zweiten Typparameters zu verwenden:
<code class="go">func Fill[X any](slice []X, f func() X) { for i := range slice { slice[i] = f() } }</code>
Diese Funktion benötigt einen zusätzlichen Parameter f, eine Funktion, die eine Instanz von X zurückgibt. Dies ermöglicht mehr Flexibilität und unterstützt das Füllen von Schnittstellen mit konkreten Typen. Um beispielsweise einen Abschnitt von sync.Locker mit sync.Mutex-Elementen zu initialisieren, kann der folgende Code verwendet werden:
<code class="go">xs := make([]sync.Locker, 10) Fill(xs, func() sync.Locker { return &sync.Mutex{} })</code>
Durch die Verwendung dieses Ansatzes können Schnittstellenabschnitte effizient mit Instanzen eines Betons gefüllt werden Typ, der eine praktische und typsichere Lösung bietet.
Das obige ist der detaillierte Inhalt vonWie kann ich einen Teil der Schnittstellen effizient mit Instanzen eines konkreten Typs in Golang füllen und gleichzeitig die Typsicherheit gewährleisten und mögliche Paniken vermeiden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!