Sans la prise en charge de la programmation générique, les bibliothèques et les applications fonctionnelles de Go sont forcées de suivre l'une des deux voies suivantes : sécurité du type + spécificité du cas d'utilisation ou non-sécurité du type + agnostic du cas d'utilisation. Avec la sortie prochaine de la version 1.18 de Go, début 2022, les génériques devraient être ajoutés au langage, ce qui permettra de nouvelles sortes de solutions de programmation fonctionnelle en Go.
S'il vise aussi la rapidité d'exécution, indispensable à la programmation système, Go considère le multithreading comme le moyen le plus robuste d'assurer sur les processeurs actuels, cette rapidité tout en rendant la maintenance facile par séparation de tâches simples exécutées indépendamment. Cette conception permet également le fonctionnement sans réécriture sur des architectures multicœurs en exploitant immédiatement l'augmentation de puissance correspondante.
Rappelons que, la généricité (ou programmation générique), consiste à définir des algorithmes identiques opérant sur des données de types différents. On définit de cette façon des procédures ou des types entiers génériques. On pourrait ainsi programmer une pile, ou une procédure qui prend l'élément supérieur de la pile, indépendamment du type de données contenues.
C'est donc une forme de polymorphisme, le « polymorphisme de type » dit aussi « paramétrage de type » : en effet, le type de donnée général (abstrait) apparaît comme un paramètre des algorithmes définis, avec la particularité que ce paramètre-là est un type. C'est un concept important pour un langage de haut niveau car il permet d'écrire des algorithmes généraux opérant sur toute une série de types : la généricité augmente donc le niveau d'abstraction des programmes écrits dans un langage qui possède cette fonctionnalité. Divers mécanismes ont été conçus pour permettre la programmation générique.
L'absence de génériques en Go était le principal point de critique de la communauté des développeurs. Il a fallu plusieurs années entre la phase de conception et l'implémentation effective qui débarquera en Go 1.18. Go est un langage typé, ce qui signifie que chaque variable et valeur du programme a un type spécifique, comme int ou string. Lorsque nous écrivons des fonctions, nous devons spécifier le type de leurs paramètres dans ce que l'on appelle la signature de la fonction, comme ceci :
Code : | Sélectionner tout |
func PrintString(s string) {}
Avec l'ajout des génériques, les bibliothèques de programmation fonctionnelle n'ont plus besoin de faire des compromis entre l'utilité et la sécurité des types. Dans l'écosystème Go, il existe déjà de nombreuses bibliothèques de programmation fonctionnelle qui varient en popularité, en fonctionnalités et en ergonomie. En raison de l'omission des génériques, elles ont toutes dû faire l'un des deux choix de conception suivants :
type safe + use- case specific
Les bibliothèques qui ont choisi cette approche ont implémenté un design qui est type safe mais seulement capable de gérer certains types prédéfinis. Sans la possibilité d'utiliser des types ou des structures personnalisés, la variété des problèmes auxquels ces bibliothèques peuvent être appliquées est limitée. Par exemple,
Code : | Sélectionner tout |
func UniqString(data []string) []string
Code : | Sélectionner tout |
func UniqInt(data []int) []int
type unsafe + use-case agnostic
Les bibliothèques qui ont choisi cette approche ont mis en œuvre une conception qui n'est pas sûre en termes de type mais qui peut être appliquée à n'importe quel cas d'utilisation. Ces bibliothèques fonctionnent avec des types et des structures personnalisés, mais avec la contrepartie que les assertions de type doivent être utilisées, ce qui expose l'application au risque d'une panique d'exécution si elle n'est pas correctement mise en œuvre. Par exemple, une fonction unique générique pourrait avoir cette signature :
Code : | Sélectionner tout |
func Uniq(data interface{}) interface{}
Go et la programmation générique
Les génériques peuvent donner des blocs de construction puissants qui permettent de partager du code et de construire des programmes plus facilement. La programmation générique consiste à écrire des fonctions et des structures de données où certains types sont laissés à spécifier ultérieurement. Avec les génériques, il est possible d’écrire une fonction qui opère sur une tranche d'un type de données arbitraire, où le type de données réel n'est spécifié que lorsque la fonction est appelée. Il est également possible de définir une structure de données qui stocke des valeurs de n'importe quel type, le type réel à stocker étant spécifié lorsque qu’une instance de la structure de données est créée.
Bien que les génériques aient des cas d'utilisation clairs, les intégrer proprement dans un langage comme Go est une tâche difficile. L'une des premières tentatives (imparfaite) d'ajouter des génériques à Go remonte à 2010. Il y en a eu plusieurs autres au cours de la dernière décennie. L'équipe de développement de go a publié un Playground de go 1.18 où chacun peut essayer d'exécuter go avec des génériques. Il existe également un compilateur expérimental qui implémente un ensemble minimal de fonctionnalités disponibles sur une branche du dépôt go. Ces deux options sont idéales pour jouer avec les génériques dans Go 1.18. Voici, ci-dessous, un cas d'utilisation.
La fonction unique a été décrite avec les deux approches de conception possibles. Avec les génériques, elle pourrait être modifiée en
Code : | Sélectionner tout |
func Uniq[T](data []T) []T
Code : | Sélectionner tout |
1 2 3 | Uniq[string any](data []string) []string // or Uniq[MyStruct any](data []MyStruct) []MyStruct |
Source : Goland
Et vous ?
Quel avenir selon vous pour la communauté et l'écosystème Go avec l'ajout des génériques et les nouvelles solutions qu'ils permettent ?
Quel est intérêt a-t-on à passer à une approche fonctionnelle si on a besoin d'écrire presque la même quantité de code ?
Voir aussi :
GoLand 2021.3 EAP est disponible. L'EDI Go de JetBrains apporte la prise en charge native des projets Go dans WSL 2, ainsi que de la correction rapide du type d'exportation
Go 1.17 est disponible et s'accompagne de la prise en charge de l'architecture ARM 64 bits sous Windows, cette version maintient la promesse de compatibilité avec Go 1
Go 1.17 Bêta apporte la prise en charge de l'architecture ARM 64 bits sous Windows, le langage devrait être en disponibilité générale en août 2021
Langage de programmation Go : combien de professionnels l'utilisent ? Où sont-ils ? Quelles sont les perspectives d'avenir du langage ? JetBrains fait un état des lieux de son écosystème