5 points par GN⁺ 2025-08-23 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Plusieurs choix de conception du langage Go ont été faits de manière inutile ou en ignorant l’expérience accumulée auparavant
  • Le problème de gestion de la portée des variables d’erreur rend la lisibilité du code et la recherche de bugs plus difficiles
  • La double nature de nil, l’utilisation mémoire, la portabilité du code et d’autres aspects révèlent une conception peu intuitive et déconnectée de la réalité
  • Les limites de l’instruction defer ainsi que la manière dont la bibliothèque standard gère les situations exceptionnelles compliquent la garantie de la sûreté face aux exceptions
  • Des problèmes accumulés comme la gestion mémoire et le traitement insuffisant de l’UTF-8 nuisent à long terme à la qualité des bases de code Go

Critique de long terme du langage Go

  • Comme je l’ai expliqué dans de précédents billets (Why Go is not my favourite language, Go programs are not portable), je souligne depuis plus de dix ans plusieurs problèmes du langage Go
  • En particulier, les choix de conception inutiles qui ignorent des bonnes pratiques déjà bien connues paraissent de plus en plus regrettables

Le manque d’intuition dans la portée des variables d’erreur

  • La syntaxe de Go élargit inutilement la portée de la variable d’erreur (err), ce qui augmente le risque d’erreurs
    • Dans le code d’exemple, la variable err reste vivante pendant toute la fonction et est réutilisée, ce qui nuit à la lisibilité et à la maintenabilité du code
    • Même les développeurs expérimentés peuvent perdre du temps et être induits en erreur lors de la recherche de bugs à cause de ces questions de portée
    • La syntaxe n’autorise pas de moyen approprié de limiter localement cette variable

Les deux formes de nil

  • Dans Go, il existe une confusion car nil ne se comporte pas de la même manière selon qu’il s’agit d’un type interface ou d’un type pointeur
    • Comme dans l’exemple ci-dessous, même si s (pointeur) et i (interface) reçoivent tous deux nil, s==i est évalué différemment, ce qui montre un comportement incohérent
    • C’est précisément le genre de problème que l’on cherche généralement à éviter dans la gestion de null, et cela donne l’impression d’une conception insuffisamment réfléchie

Les limites de la portabilité du code

  • L’utilisation de commentaires pour la compilation conditionnelle est nettement inefficace du point de vue de la maintenance et de la portabilité
    • Quiconque a déjà développé un logiciel réellement portable sait qu’une telle approche est lourde et source d’erreurs
    • L’expérience accumulée historiquement en matière de portabilité du code et de cas pratiques a été ignorée
    • Voir Go programs are not portable pour plus de détails

Le manque de clarté sur la propriété avec append

  • La relation de propriété entre la fonction append et les slices n’est pas claire, ce qui rend le code difficile à prévoir
    • L’exemple montre qu’il est difficile de savoir à l’avance quel effet un append effectué dans une fonction foo aura réellement sur l’original
    • Le langage accumule ainsi des « quirks » qu’il faut connaître, ce qui favorise les erreurs

Une conception inaboutie de defer

  • Go ne fournit pas de support clair pour la libération des ressources, contrairement au principe RAII (Resource Acquisition Is Initialization)
    • Par rapport aux structures de gestion des ressources de Java et Python, Go ne permet pas de savoir clairement quelles ressources doivent être libérées avec defer
    • Comme le montre l’exemple des fichiers, il faut même gérer soi-même les problèmes de double fermeture, et l’ordre ainsi que la méthode corrects de libération restent flous

La gestion des exceptions dans la bibliothèque standard

  • Go ne prend pas en charge les exceptions explicites, mais des situations exceptionnelles comme panic existent malgré tout
    • Dans certains cas, panic ne provoque pas un arrêt complet du programme et peut au contraire être absorbé
    • La bibliothèque standard (fmt.Print, serveur HTTP, etc.) contient des schémas où les exceptions sont ignorées, ce qui rend impossible toute véritable garantie de sûreté face aux exceptions
    • En pratique, écrire du code sûr face aux exceptions reste indispensable, sans qu’il soit possible d’utiliser directement des exceptions

Le traitement de l’UTF-8 et des chaînes

  • Même si l’on place des données binaires arbitraires dans le type string, Go fonctionne sans validation particulière
    • Des noms de fichiers créés avant l’ère de l’encodage UTF-8 peuvent ainsi être silencieusement omis
    • Lors de sauvegardes, cela peut entraîner la perte de données importantes, ce qui reflète une approche simpliste peu alignée avec la réalité du terrain

Les limites de la gestion mémoire

  • Il est difficile de contrôler directement l’utilisation de la RAM, et la fiabilité du GC (garbage collector) a aussi ses limites
    • La consommation mémoire de Go augmente, ce qui finit par créer des problèmes de coût et de performance
    • Dans des environnements à multiples instances ou conteneurs, des problèmes réels de coût et de passage à l’échelle apparaissent

Conclusion : il existait de meilleures voies

  • Alors qu’il existait déjà des conceptions de langage ayant fait leurs preuves, Go les a ignorées sur de nombreux points
    • Contrairement aux problèmes des premières versions de Java, de meilleures approches existaient déjà au moment de la sortie de Go

Références

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.