Dans Go 1.18, les génériques permettent aux développeurs de définir des fonctions et des structures de données qui fonctionnent sur un plus large éventail de types. Cependant, un scénario spécifique est apparu dans lequel les utilisateurs cherchent à utiliser des génériques avec des interfaces tout en fournissant également un type concret pour les paramètres de type générique.
Considérez la fonction suivante qui vise à remplir une tranche avec nouvelles instances d'un type concret :
<code class="go">func Fill[X any](slice []*X) { for i := range slice { slice[i] = new(X) } }</code>
Cette fonction fonctionne comme prévu lors du remplissage d'une tranche de pointeurs vers un type spécifique, tel que []*int. Cependant, si la tranche est constituée d'interfaces et que la fonction est appelée avec un type concret pour le paramètre générique, la compilation échoue.
<code class="go">xs := make([]sync.Locker, 10) // fill with nils Fill[sync.Locker,sync.Mutex](xs) // ouch</code>
Le problème se pose car la contrainte des deux paramètres de type X et Y à any supprime la relation entre l'interface et sa mise en œuvre concrète. Au moment de la compilation, on sait seulement que X et Y sont des types distincts.
Pour résoudre ce problème, une assertion explicite peut être utilisée :
<code class="go">func Fill[X, Y any](slice []X) { for i := range slice { slice[i] = any(*new(Y)).(X) } }</code>
Cependant, cette solution introduit des paniques d'exécution potentielles si Y n'implémente pas X. De plus, si Y est un type pointeur, les informations de type de base sont perdues, ce qui entraîne des valeurs nulles au lieu d'instances du type concret souhaité.
Une meilleure approche consiste à utiliser une fonction constructeur au lieu d'un deuxième paramètre générique, comme démontré ci-dessous :
<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>
Cette solution fournit un moyen plus robuste et idiomatique de remplir une tranche avec des instances d'un type concret spécifique tout en maintenir la sécurité des types.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!