Covariance dans les génériques Golang 1.18 : comprendre ses limites
L'introduction des génériques par Golang 1.18 a apporté de nombreux progrès, mais certaines limitations subsistent, notamment l'absence de prise en charge complète de la covariance.
Comprendre le Problème
Considérons un scénario dans lequel vous souhaitez définir une fonction générique appelée Pipe qui prend deux fonctions :
Le le but est de créer une fonction qui exécute la sortie de gauche comme entrée de droite. Cependant, l'implémentation suivante ne parvient pas à se compiler dans certains cas :
func Pipe[A, T1, T2 any](left func(A) T1, right func(T1) T2) func(A) T2 { return func(a A) T2 { return right(left(a)) } }
Ce problème se pose car les génériques Golang ne prennent pas entièrement en charge la covariance. La covariance signifie qu'un paramètre de type peut être remplacé par un sous-type sans violer le contrat. Dans ce cas, T1 n'autorise pas les sous-types alors que io.ReadCloser est un sous-type de io.Reader.
Décision de conception de Golang
Décision de Golang de ne pas implémenter pleinement la covariance est basé sur des considérations de sécurité. Autoriser la covariance pourrait conduire à des situations dans lesquelles des fonctions sont appelées avec des types qui ne correspondent pas à leurs signatures prévues, ce qui entraînerait un comportement indéfini.
Clarifications de la FAQ
La FAQ de Golang indique explicitement que le comportement actuel est intentionnel et non un bug. Cette décision vise à éviter les erreurs d'exécution inattendues qui pourraient nuire à la fiabilité des applications.
Types convertibles et types covariants
Bien que Golang ne prenne pas en charge la covariance complète, il permet le conversion d'un type à un autre. Cependant, dans le cas de func Pipe, il n'y a aucun moyen de représenter cette conversion à l'aide de paramètres de type.
Comme alternative, vous pouvez explicitement convertir le résultat de left dans le type requis par right. Cependant, cette approche n'est pas sécurisée au moment de la compilation, comme le montre le code modifié suivant :
func Pipe[A, T1, T2, T3 any](left func(A) T1, right func(T2) T3) func(A) T3 { return func(a A) T3 { return right(any(left(a)).(T2)) } }
Bien que cela puisse faire le travail, cela sacrifie la sécurité au moment de la compilation pour la conversion à l'exécution.
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!