"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > ## Comment initialiser des tranches d'interfaces avec des types concrets dans Go ?

## Comment initialiser des tranches d'interfaces avec des types concrets dans Go ?

Publié le 2024-11-10
Parcourir:235

## How to Initialize Slices of Interfaces with Concrete Types in Go?

Initialisation générique avec des interfaces et des types concrets dans Go

Lors de l'écriture de fonctions génériques dans Go, il peut être avantageux d'accepter également des types concrets. Cependant, cela pose un défi lorsque l'on tente d'initialiser des tranches d'interfaces avec de nouvelles instances de ces types spécifiques.

Tentatives initiales avec plusieurs paramètres de type

Une approche peut sembler logique : définir deux paramètres de type, un pour le type d'élément slice (X) et un pour le type concret (Y) à instancier. Cependant, cette approche échoue lorsque vous essayez d'attribuer une instance de Y à un élément de type X.

func Fill[X, Y any](slice []X){
   for i := range slice {
      slice[i] = new(Y) // not work!
   }
}

Ce problème survient car le compilateur perd la relation entre l'interface X et son implémentation Y. X et Y sont traités comme des types distincts.

Utilisation du casting explicite

Pour résoudre ce problème, on peut utiliser une opération de conversion explicite dans la fonction :

func Fill[X, Y any](slice []X) {
    for i := range slice {
        slice[i] = any(*new(Y)).(X)
    }
}

Cependant, cette approche déclenche une panique si Y n'implémente pas X, ce qui se produit dans des scénarios tels que la tentative d'attribuer un *sync.Mutex (type de pointeur) à sync.Locker.

Utilisation d'une fonction constructeur

Une solution plus robuste et plus sûre implique l'utilisation d'une fonction constructeur :

func Fill[X any](slice []X, f func() X) {
    for i := range slice {
        slice[i] = f()
    }
}

Cette fonction accepte une fonction constructeur qui renvoie une nouvelle instance du type spécifié. Cela permet une initialisation concise et sûre des tranches avec des instances de type concret.

Éviter les valeurs nulles

Dans les cas où le type concret est destiné à être instancié avec un type pointeur, il est important de noter ce new(Y) donnera une valeur nulle. Pour contourner cela, on peut ajuster la fonction constructeur pour renvoyer la valeur correcte du pointeur, comme func() X { return &sync.Mutex{} }.

Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3