Generics en Go : pourquoi en a-t-on besoin et comment les utiliser en pratique

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi les Generics en Go sont-ils une avancée ?



Pendant longtemps, le langage Go (Golang) est resté l'un des rares langages modernes sans support de la programmation générique (generics). Les développeurs étaient contraints d'utiliser interface{} et le transtypage, ce qui entraînait une perte de sécurité des types à la compilation et alourdissait le code. Avec la sortie de Go version 1.18 (février 2022), la situation a radicalement changé.



Les Generics sont un mécanisme permettant d'écrire des fonctions et des structures de données pouvant fonctionner avec n'importe quel type, tout en conservant un typage strict. Dans cet article, nous verrons pourquoi ils sont nécessaires et montrerons avec des exemples pratiques comment les utiliser dans le développement quotidien en Go.



Pourquoi les Generics sont-ils nécessaires en Go ?



Avant l'arrivée des generics, pour créer des fonctions universelles, les développeurs utilisaient interface{} (interface vide). Prenons l'exemple classique d'une fonction qui trouve l'élément minimum dans une slice :



// Sans generics (Go < 1.18)func MinInt(a, b int) int {    if a < b {        return a    }    return b}

func MinFloat(a, b float64) float64 { if a < b { return a } return b}


Pour chaque type, il fallait écrire une fonction séparée. Avec interface{}, on pouvait faire ceci :



func MinInterface(a, b interface{}) interface{} {    // Nécessite un transtypage et une vérification à l'exécution    // Ce n'est ni sûr ni efficace}


Les problèmes de cette approche sont évidents :

  • Perte de sécurité des types — une erreur peut n'apparaître qu'à l'exécution.
  • Nécessité de transtyper — le code devient lourd.
  • Baisse des performances — travailler avec des interfaces nécessite des opérations supplémentaires.


Les Generics résolvent tous ces problèmes. Ils permettent :

  • D'écrire des algorithmes universels une seule fois.
  • De conserver une vérification stricte des types à la compilation.
  • D'éliminer le transtypage et d'améliorer les performances.


Les bases de la syntaxe des Generics en Go



Les generics en Go sont basés sur des paramètres de type. La syntaxe est simple et intuitive. Les paramètres de type sont indiqués entre crochets après le nom de la fonction ou du type.



1. Fonction simple avec generics



Écrivons la même fonction de minimum, mais cette fois avec des generics :



package main

import "fmt"

// Min retourne la valeur minimale des deuxfunc Min[T comparable](a, b T) T { if a < b { return a } return b}

func main() { fmt.Println(Min[int](10, 20)) // 10 fmt.Println(Min[float64](3.14, 2.71)) // 2.71 fmt.Println(Min[string]("abc", "xyz")) // abc}


Ici, [T comparable] est le paramètre de type. comparable est une contrainte intégrée qui garantit que le type supporte les opérateurs de comparaison == et !=. Notez : pour l'opérateur <, il faut utiliser la contrainte constraints.Ordered (du paquet golang.org/x/exp/constraints) ou écrire la vôtre.



2. Contraintes (Constraints)



Les contraintes sont des interfaces qui définissent les méthodes et opérations que les types doivent supporter. Dans Go 1.18+, le paquet constraints est apparu (actuellement dans golang.org/x/exp), mais vous pouvez créer vos propres contraintes.



import "golang.org/x/exp/constraints"

// MinOrdered fonctionne uniquement avec les types ordonnésfunc MinOrdered[T constraints.Ordered](a, b T) T { if a < b { return a } return b}


Contrainte personnalisée pour les types supportant la méthode String() :



Blogs

Book Recommendations