Heim >Backend-Entwicklung >Golang >Wie füllt man einen Abschnitt mit konkreten Implementierungen mithilfe von Golang-Generika und -Schnittstellen?
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.
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>
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>
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.
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>
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>
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!