Go 1.27 est sorti le mercredi 19 août 2026, et la nouveauté mise en avant est la méthode générique, mais le changement qui touchera le plus sûrement vos compilations est celui que personne n'annonce fort. Le paquet encoding/json existant repose désormais sur le nouveau moteur encoding/json/v2. Le comportement est préservé et l'ancienne API continue de fonctionner, aucune migration n'est donc exigée, mais les messages d'erreur peuvent différer et le décodage devient nettement plus rapide. Ajoutez une allocation spécialisée par taille qui réduit d'environ trente pour cent le coût des petites allocations, un paquet uuid dans la bibliothèque standard et quatre nouveaux modernizers go fix.
The short answer
Go 1.27 est sorti le mercredi 19 août 2026. Les méthodes peuvent désormais déclarer leurs propres paramètres de type, les littéraux de structure acceptent tout sélecteur de champ valide, et la bibliothèque standard gagne uuid, encoding/json/v2 et encoding/json/jsontext. Le paquet encoding/json existant repose maintenant sur l'implémentation v2, comportement préservé, même si les messages d'erreur peuvent différer. L'allocation spécialisée par taille réduit jusqu'à trente pour cent le coût des petites allocations pour environ soixante kilooctets de binaire en plus.
Lisez vite l'annonce de Go 1.27 et vous en ressortez avec l'idée que cette version parle de méthodes génériques. Lisez sérieusement les notes de version et vous trouvez un paquet de la bibliothèque standard reconstruit en silence sous une API que des millions de lignes de code importent déjà.
Le moteur JSON a changé, pas le chemin d'import
Go 1.27 ajoute deux paquets. Le premier est encoding/json/v2, une révision majeure qui offre Marshal, MarshalWrite, MarshalEncode, Unmarshal, UnmarshalRead et UnmarshalDecode, tous acceptant des arguments Options variadiques pour rendre le comportement configurable plutôt que figé. Le second est encoding/json/jsontext, qui traite la couche syntaxique avec les types Encoder, Decoder, Token et Value, pour ceux qui veulent parcourir du JSON en flux sans construire de valeurs Go.
Vient ensuite la partie qui concerne tous les autres. Le paquet encoding/json existant s'appuie désormais sur v2. Vous ne changez pas un import, vous ne changez pas une balise de structure, et les notes de version indiquent clairement que l'API v1 reste prise en charge et que la migration n'est pas requise.
Le comportement est préservé. Les messages d'erreur peuvent différer.
Cette seconde phrase résume tout le risque de mise à jour. Les bases de code Go comparent des textes d'erreur plus souvent que personne ne l'admet, en général dans les tests, parfois dans un gestionnaire qui tente d'indiquer au client quel champ était mal formé. Ce sont ces endroits à inspecter avant de changer de chaîne d'outils, pas le code d'encodage lui même.
La forme des gains de performance mérite aussi d'être connue. L'encodage est au niveau de l'ancienne implémentation. Le décodage est nettement plus rapide. La plupart des services analysent plus de JSON qu'ils n'en émettent, le gain tombe donc là où se trouve la charge.
Où se loge la rigueur
Le paquet v2 retient des valeurs par défaut plus strictes et plus interopérables que v1. Il rejette l'UTF-8 invalide dans les chaînes JSON et il rejette les noms dupliqués dans un objet JSON. Deux choses que v1 accepte, et deux choses qu'un producteur correct ne devrait jamais émettre.
Le détail important, c'est que ces valeurs par défaut appartiennent à v2, pas à la couche de compatibilité v1. Continuez d'importer encoding/json et vous gardez la sémantique v1 sur un moteur v2. Changez votre import pour encoding/json/v2 et vous emportez le comportement strict avec vous.
Cela rend le chemin de migration agréablement ennuyeux. Vous pouvez mettre à jour la chaîne d'outils sur toute une flotte sans toucher à la sémantique JSON, puis basculer les services vers v2 un par un, quand vous serez prêt à découvrir quel fournisseur vous envoie des clés d'objet dupliquées depuis des années.
Si quelque chose se passe mal, compiler avec GOEXPERIMENT=nojsonv2 restaure l'implémentation v1 d'origine. Les notes précisent que ce drapeau devrait disparaître dans une version future, il vous achète donc une fenêtre de déploiement, pas un retrait définitif.
Les méthodes génériques, et les changements plus discrets
Les méthodes peuvent désormais déclarer leurs propres paramètres de type. L'exemple de la bibliothèque standard est math/rand/v2, où N n'était disponible que comme fonction de paquet et devient aussi une méthode sur Rand. Les méthodes d'interface sont exclues, elles ne peuvent pas déclarer de paramètres de type, ce qui garde les ensembles de méthodes traitables et évite la catégorie de problèmes qui avait tenu les méthodes génériques hors de Go 1.18.
Deux changements plus discrets apparaîtront dans le code ordinaire plus vite que celui là. Les littéraux de structure acceptent maintenant tout sélecteur de champ valide pour le type concerné, vous pouvez donc initialiser directement un champ imbriqué ou embarqué au lieu d'écrire le littéral intermédiaire à la main. Et l'inférence de type des fonctions s'applique désormais dans tous les contextes d'affectation, y compris les littéraux composites, les conversions et les envois sur canal, ce qui supprime encore une série d'endroits où il fallait expliciter un argument de type que le compilateur pouvait déduire.
L'histoire des génériques est ici incrémentale plutôt que spectaculaire, ce qui reste cohérent avec la trajectoire du langage. Nous avions observé le même schéma quand la proposition d'ensembles et de tables ordonnées pour la bibliothèque standard est apparue pour une version ultérieure.
L'allocation, et le pour cent qui compte à grande échelle
Le compilateur génère désormais des routines d'allocation mémoire spécialisées par taille. L'effet mesuré est une réduction pouvant atteindre trente pour cent du coût des petites allocations, définies comme inférieures à quatre vingts octets, ce que les notes de version convertissent en une amélioration attendue d'environ un pour cent pour les programmes gourmands en allocations.
Un pour cent, cela semble insignifiant. Lisez le comme un pour cent de moins sur la facture de calcul de chaque service Go que vous exploitez, obtenu en recompilant, et cela se lit autrement. Le coût est d'environ soixante kilooctets de binaire supplémentaire, et les notes précisent que ce chiffre ne dépend pas de la charge, ce sont donc soixante kilooctets que vous livriez un plan de contrôle ou un conteneur adjoint. GOEXPERIMENT=nosizespecializedmalloc permet de s'en retirer et devrait disparaître dans Go 1.28.
À côté de cela, le profil de fuite de goroutines dans runtime/pprof passe en disponibilité générale après avoir été expérimental dans Go 1.26. Si vous avez déjà traqué une fuite lente dans un service de longue durée et abandonné faute d'outillage prêt, il est prêt maintenant. Le réglage GODEBUG asynctimerchan a été supprimé définitivement.
Le reste de la bibliothèque standard
Un paquet uuid entre dans la bibliothèque standard, ce qui retire l'une des dépendances mono usage les plus courantes des projets Go.
Le paquet crypto/mldsa implémente ML-DSA, le schéma de signature normalisé sous la référence FIPS 204. Disposer d'une primitive de signature post quantique dans la bibliothèque standard plutôt que dans un module tiers, c'est le genre de changement qui ne compte que le jour où vous en avez besoin, et qui compte alors beaucoup.
Le paquet expérimental simd arrive avec des types portables indépendants de la taille de vecteur comme Int8s et Float32s, disponibles sur toutes les architectures et conditionnés à GOEXPERIMENT=simd au moment de la compilation. Le paquet simd/archsimd, spécifique à l'architecture, poursuit le travail de Go 1.26 avec des API amd64 révisées, une nouvelle prise en charge Neon sur arm64 en 128 bits et une nouvelle prise en charge WebAssembly en 128 bits. Les vecteurs de 256 et 512 bits restent limités à certains processeurs amd64. Aucun de ces deux paquets n'a d'API stable.
Les tests gagnent net/http/httptest.NewTestServer, qui construit un faux réseau en mémoire au lieu d'ouvrir un vrai port. Quiconque a vu un exécuteur d'intégration continue échouer parce que deux paquets de tests parallèles voulaient le même port éphémère comprendra l'intérêt.
Ce qu'il faut faire cette semaine
Mettez d'abord à jour un service non critique et lisez sa sortie d'erreur plutôt que sa courbe de latence. Le changement de moteur JSON est conçu pour être invisible, et il le sera le plus souvent, mais la seule différence documentée se trouve exactement là où vos tests sont le plus susceptibles d'être stricts.
Cherchez ensuite dans toute la base de code les comparaisons de chaînes d'erreur autour du décodage JSON. Cette seule recherche couvre l'essentiel du risque réel de cette version.
Après quoi les gains sont gratuits. Recompilez tout pour le changement d'allocateur, supprimez votre dépendance uuid, et gardez GOEXPERIMENT=nojsonv2 noté quelque part comme le levier que l'on tire à trois heures du matin, pas comme la ligne que l'on ajoute au Dockerfile aujourd'hui.
Sources et pour aller plus loin
- Go 1.27 is released, blog Go, 19 août 2026
- Notes de version de Go 1.27, go.dev
- Go Language 1.27 Adds Generic Methods, Struct Improvement and More SIMD, Phoronix, août 2026
- Go 1.27 Released with Generic Methods, JSON v2, and Faster Memory Allocation, Linuxiac, août 2026
Questions fréquentes
Dois je migrer vers encoding/json/v2 ?
Non, et c'est tout l'intérêt de la façon dont la sortie a été menée. L'API v1 d'encoding/json reste prise en charge et les notes de version disent explicitement que la migration n'est pas requise. Ce qui a changé se situe en dessous : encoding/json s'appuie désormais sur le moteur v2. Le comportement est préservé, vos balises de structure, vos marshalleurs personnalisés et vos allers retours font donc ce qu'ils faisaient. La seule réserve à noter est que les messages d'erreur peuvent différer. Si un test ou un chemin de code compare le texte d'une erreur JSON plutôt que son type, c'est là qu'une mise à jour silencieuse devient une compilation en échec.
Qu'est ce qui est plus strict dans v2, et cette rigueur atteint elle v1 ?
Le paquet v2 retient des valeurs par défaut plus strictes et plus interopérables que v1. Il rejette l'UTF-8 invalide à l'intérieur des chaînes JSON et il rejette les noms dupliqués dans un objet JSON, deux choses que v1 tolère. Ces valeurs par défaut s'appliquent quand vous importez directement encoding/json/v2, pas quand vous conservez encoding/json, qui garde sa propre sémantique. La rigueur est donc optionnelle. Cela compte si vous consommez du JSON produit par des systèmes que vous ne maîtrisez pas, car une charge utile acceptée pendant des années peut se mettre à renvoyer une erreur le jour où vous changez le chemin d'import. Basculez un service, observez, puis passez au suivant.
Quelle est la porte de sortie si le nouveau moteur pose problème ?
Compilez avec GOEXPERIMENT=nojsonv2 et la chaîne d'outils restaure l'implémentation v1 d'origine. C'est volontairement temporaire : les notes de version indiquent que ce drapeau devrait disparaître dans une version future, traitez le donc comme un moyen de débloquer un déploiement pendant que vous cherchez la vraie cause, pas comme un réglage permanent de votre chaîne de compilation. Le même schéma s'applique au changement d'allocateur, où GOEXPERIMENT=nosizespecializedmalloc permet de se retirer et devrait disparaître dans Go 1.28. Ces deux drapeaux existent parce que l'équipe Go s'attend à ce qu'un petit nombre de programmes s'en aperçoivent, pas parce qu'elle redoute un problème général.
Quel gain de vitesse en pratique ?
Deux chiffres distincts, et aucun n'est un facteur spectaculaire. Côté JSON, l'encodage est au niveau de v1 tandis que le décodage est nettement plus rapide, ce qui convient au cas courant où un service analyse beaucoup plus de JSON qu'il n'en produit. Côté allocation, le compilateur génère désormais des routines d'allocation spécialisées par taille qui réduisent jusqu'à trente pour cent le coût des petites allocations de moins de quatre vingts octets, ce que les notes traduisent par environ un pour cent de mieux sur l'ensemble pour les programmes gourmands en allocations. La contrepartie est une soixantaine de kilooctets de binaire supplémentaire, indépendamment de la charge. Un pour cent est réel à l'échelle d'une flotte et invisible sur un test portable.
Qu'est ce qui change dans l'outillage au quotidien ?
Quatre nouveaux modernizers go fix arrivent : atomictypes, embedlit, slicesbackward et unsafefuncs. Le modernizer fmtappendf a été retiré pour des raisons stylistiques et waitgroup a été renommé waitgroupgo afin de lever une ambiguïté, une tâche d'intégration continue qui fige des noms de modernizers mérite donc un coup d'oeil. Au delà de go fix, go doc accepte désormais des requêtes de la forme paquet et version, ce qui permet de lire la documentation d'une version que vous n'avez pas encore vendorée, et go mod tidy regroupe plusieurs blocs require en un seul. Sur macOS, l'éditeur de liens a gagné deux options pour fixer les versions inscrites dans la commande de chargement LC_BUILD_VERSION.