MFormations
Modern Go Engineering

Chapitre 24

24 - Tendances

> Les tendances actuelles et futures de l'écosystème Go : 2024-2026 et au-delà.

Cours 24 : Tendances de l'écosystème Go

300+ lignes d'analyse des tendances 2024-2026.


1. Go 1.23+ : Range over Func et Iterators

Introduction

Go 1.22 a introduit le range over int, et Go 1.23 a généralisé le range pour fonctionner avec des fonctions itératrices. C'est le changement le plus significatif depuis les generics (Go 1.18).

Syntaxe de base

// Go 1.22 : range over int
for i := range 5 {
    fmt.Println(i) // 0, 1, 2, 3, 4
}

// Go 1.23 : range over func (iterators)
for v := range myIterator {
    fmt.Println(v)
}

Le package iter

import "iter"

// Un iterateur est une fonction avec cette signature :
// func(yield func(T) bool) bool

// Seq[T] = func(yield func(T) bool) bool
// Seq2[T, U] = func(yield func(T, U) bool) bool

Exemple : Iterateur personnalisé

// Iterateur sur une arborescence
func Walk(root *Node) iter.Seq[*Node] {
    return func(yield func(*Node) bool) {
        var walk func(*Node) bool
        walk = func(n *Node) bool {
            if n == nil {
                return true
            }
            if !yield(n) {
                return false
            }
            if !walk(n.Left) {
                return false
            }
            return walk(n.Right)
        }
        walk(root)
    }
}

// Usage
for node := range Walk(root) {
    fmt.Println(node.Value)
}

Exemple : Pagination

func Paginate[T any](items []T, pageSize int) iter.Seq2[int, []T] {
    return func(yield func(int, []T) bool) {
        for i := 0; i < len(items); i += pageSize {
            end := i + pageSize
            if end > len(items) {
                end = len(items)
            }
            if !yield(i/pageSize, items[i:end]) {
                return
            }
        }
    }
}

// Usage
for page, items := range Paginate(allItems, 20) {
    fmt.Printf("Page %d: %v\n", page, items)
}

Standard library avec iterators

// maps.All, maps.Keys, maps.Values
for k, v := range maps.All(myMap) {
    fmt.Println(k, v)
}

// slices.All, slices.Values, slices.Backward
for i, v := range slices.All(mySlice) {
    fmt.Println(i, v)
}
for v := range slices.Backward(mySlice) {
    // Itération inverse
}

Impact

  • + Performances : les itérateurs sont paresseux (lazy), pas d'allocation intermédiaire
  • + Expressivité : code plus déclaratif
  • + Compatibilité : toutes les bibliothèques peuvent exposer des iterators
  • - Complexité : la signature func(yield func(T) bool) bool est intimidante

Limitations

  • Pas de break ou continue personnalisés dans l'iterateur (le yield retourne false pour break)
  • Pas de try-catch dans l'iterateur
  • Les iterators ne sont pas des types de première classe (pas de stockage dans une variable)

2. WebAssembly (WASM)

État actuel

Go compile en WASM depuis Go 1.11 (2018). Aujourd'hui, le support est mature, avec des améliorations significatives :

VersionAmélioration
Go 1.11Support WASM initial (js/wasm)
Go 1.19WebAssembly System Interface (WASI) preview 1
Go 1.21Améliorations WASI
Go 1.23WASI preview 2 support, meilleure performance

Exemple : Application WASM

package main

import (
    "syscall/js"
)

func main() {
    c := make(chan struct{}, 0)
    js.Global().Set("compute", js.FuncOf(compute))
    <-c
}

func compute(this js.Value, args []js.Value) interface{} {
    input := args[0].String()
    result := process(input)
    return js.ValueOf(result)
}

Build WASM

# Pour navigateur (js/wasm)
GOOS=js GOARCH=wasm go build -o main.wasm main.go

# Pour edge runtime (WASI)
GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go

Cas d'usage

  1. Edge Computing : Cloudflare Workers, Fastly Compute, Fermyon Spin
  2. Plugin Systems : exécution de code utilisateur dans un sandbox
  3. Frontend : avec Vue.js/React via des frameworks comme Vugu
  4. Serverless : fonctions serverless en Go compilées en WASM
  5. IoT : exécution de code Go sur des devices contraints

Frameworks WASM pour Go

FrameworkDescription
VuguComposants web en Go (similaire à Vue.js)
GioUI multiplateforme (mobile, desktop, web)
TinyGoCompilateur pour petits devices (WASM friendly)
WazeroRuntime WASM zero-dependency en Go

Limitations actuelles

  • Taille du binaire (~10MB pour une app simple)
  • Pas de goroutines en WASI (GOOS=wasip1)
  • Pas d'accès complet au système (système de fichiers, réseau)
  • Performance inférieure au natif

3. AI/ML avec Go

Positionnement de Go dans l'écosystème AI

Go n'est pas un langage de training ML (Python domine), mais il excelle dans l'infrastructure autour du ML :

Python (Training) -------> ONNX/TensorRT -------> Go (Serving)
         │                                           │
         │  Data pipelines                           │  API
         │  Feature stores                           │  Scaling
         │  ETL                                      │  Monitoring
         ▼                                           ▼
    [Python tools]                             [Go services]

Bibliothèques ML en Go

// goml : bibliothèque ML en Go pur
import "github.com/cdipaolo/goml"

// Gorgonia : réseau de neurones (comme PyTorch)
import "gorgonia.org/gorgonia"
import "gorgonia.org/tensor"

// OpenCV : vision par ordinateur
import "gocv.io/x/gocv"

// ONNX Runtime : inférence ONNX
import "github.com/yalue/onnxruntime_go"

Exemple : Inférence ONNX en Go

package main

import (
    "github.com/yalue/onnxruntime_go"
)

func main() {
    // Charger un modèle ONNX exporté depuis Python
    rt, _ := onnxruntime_go.NewRuntime()
    defer rt.Close()

    inputTensor, _ := onnxruntime_go.NewTensor(...)
    outputTensor, _ := onnxruntime_go.NewEmptyTensor(...)

    session, _ := onnxruntime_go.NewSession("model.onnx", input, output)
    defer session.Destroy()

    session.Run()
    result := outputTensor.GetData()
}

Go dans les data pipelines

// Pipeline feature engineering avec Go
type FeaturePipeline struct {
    transformers []Transformer
}

type Transformer interface {
    Transform(ctx context.Context, data []Record) ([]Feature, error)
}

// Ce pattern est très utilisé dans des outils comme
// Feast (feature store) écrit en Go

Tendances AI/Go 2025-2026

  1. Model serving : Go est le langage dominant pour servir des modèles ML en production

    • TensorFlow Serving (C++, bindings Go)
    • TorchServe (Java, mais alternative Go : Cortex)
    • Custom inference servers en Go
  2. Vector databases : Go utilisé dans Milvus, Weaviate, Qdrant

  3. RAG (Retrieval-Augmented Generation) : Go pour les pipelines de retrieval

    • Embeddings, vector search, reranking
  4. Feature stores : Feast (Go), Tecton

  5. Data engineering : Go pour les pipelines ETL haute performance

Limitations

  • Pas de GPU computing natif (CUDA via CGO)
  • Écosystème ML moins riche que Python
  • Pas de Jupyter Notebook-like pour l'exploration
  • Communauté ML plus petite

4. Go Generics Adoption

État des lieux (2026)

Les generics (Go 1.18, 2022) sont maintenant largement adoptés :

  • 2022 : adoption prudente, bugs, limitations
  • 2023 : adoption croissante dans les bibliothèques
  • 2024 : maturité, la plupart des nouvelles bibliothèques utilisent les generics
  • 2025-2026 : standard de facto

Patterns de generics adoptés

// 1. Conteneurs typés (Stack, Queue, Cache)
type Stack[T any] struct { ... }

// 2. Higher-order functions (Map, Filter, Reduce)
func Map[T, U any](s []T, f func(T) U) []U { ... }

// 3. Repository pattern
type Repository[T, ID comparable] interface {
    Get(ctx context.Context, id ID) (*T, error)
    Create(ctx context.Context, entity *T) error
    Update(ctx context.Context, entity *T) error
    Delete(ctx context.Context, id ID) error
}

// 4. Type-safe builders
type Option[T any] func(*T)

// 5. Sum types (discriminated unions) avec generics
type Result[T any] struct {
    Value T
    Err   error
}

Impact sur la stdlib

// Avant (interfaces + assertions)
sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })

// Après (si stdlib évolue - proposition)
slices.SortFunc(s, func(a, b T) int { return cmp.Compare(a, b) })

Limitations persistantes

  1. Méthodes génériques : toujours pas possible (seuls les types peuvent avoir des params)
  2. Performance : monomorphisation augmente la taille du binaire
  3. Complexité : les signatures avec des contraintes complexes sont dures à lire
  4. Interopérabilité : une Stack[int] et une Stack[string] sont des types différents

Prédictions

  • Constraint inference améliorée
  • Méthodes génériques (Go 2.0?)
  • Meilleure intégration avec les interfaces
  • Adoption massive dans les ORM (gorm v3+)

5. Framework Evolution

Le retour du stdlib

Tendance forte : les frameworks "batteries-included" (Gin, Echo, Fiber) perdent du terrain face au stdlib enrichi.

Avant (2015-2020) :

// Nécessité d'un framework pour le routage
r := gin.Default()
r.GET("/api/users", handler)

Après (2024+) :

// Go 1.22+ : routage avancé dans le stdlib
mux.HandleFunc("GET /api/users/{id}", handler)
id := r.PathValue("id")

Évolution des frameworks

FrameworkTendanceRaison
chiStableRoutage simple, middleware
GinStablePerformance, grande communauté
FiberStableExpress-like, performance
EchoStableMiddleware, documentation
gorilla/muxArchiveAbandonné, plus maintenu
stdlibCroissanceGo 1.22+ routage amélioré

Nouveaux venus

// Huma : API REST avec OpenAPI généré
import "github.com/danielgtaylor/huma/v2"

type GreetingInput struct {
    Name string `path:"name"`
}
type GreetingOutput struct {
    Message string `json:"message"`
}

huma.Get(api, "/greeting/{name}", func(ctx context.Context, input *GreetingInput) (*GreetingOutput, error) {
    return &GreetingOutput{Message: fmt.Sprintf("Hello, %s!", input.Name)}, nil
})

Connect (gRPC + HTTP)

// Connect : Unifie gRPC et HTTP
import "connectrpc.com/connect"

greetClient := greetv1connect.NewGreetServiceClient(httpClient, baseURL)
greetResponse, err := greetClient.Greet(ctx, connect.NewRequest(&greetv1.GreetRequest{
    Name: "Jane",
}))

Tendances frameworks

  1. API-first avec génération automatique de clients (Connect, Huma)
  2. OpenAPI intégrée : spécification générée depuis le code
  3. Déclin des mega-frameworks : préférence pour des bibliothèques composables
  4. Type-safe routing : paramètres de route typés

6. Go in Embedded

TinyGo : le compilateur pour l'embarqué

// Clignotement de LED avec TinyGo
package main

import (
    "machine"
    "time"
)

func main() {
    led := machine.LED
    led.Configure(machine.PinConfig{Mode: machine.PinOutput})

    for {
        led.High()
        time.Sleep(time.Millisecond * 500)
        led.Low()
        time.Sleep(time.Millisecond * 500)
    }
}

Compilation :

tinygo build -target=arduino-nano33 -o firmware.hex main.go

Plateformes supportées

PlateformeMicrocontrôleurRAM
ArduinoATmega328P2KB
ESP32Xtensa LX6520KB
Raspberry Pi PicoRP2040264KB
STM32ARM Cortex-M20KB-2MB
nRF52ARM Cortex-M464KB-256KB

Cas d'usage concrets

  1. IoT Sensors : collecte de données environnementales
  2. Edge Computing : processing local avant envoi cloud
  3. Drone controllers : vol stationnaire et navigation
  4. Smart home : domotique avec MQTT
  5. Robotics : contrôle de moteurs

Limitations

  • Go standard nécessite un OS (pas de bare metal)
  • TinyGo supporte un sous-ensemble du langage (pas de reflect, unsafe limité)
  • Pas de goroutines sur les très petits devices
  • Taille de binaire plus grande que C

7. Go 2.0 : Spéculations

Timeline probable

2024-2025 : Go 1.23, 1.24 (features incrémentales)
2025-2026 : Go 1.25, 1.26 (préparation Go 2.0)
2026-2027 : Go 2.0 annoncé (ou renommé)
2027-2028 : Go 2.0 released

Features potentielles

  1. Generics improvements :

    • Méthodes génériques
    • Covariance/contravariance
    • Better type inference
  2. Error handling :

    • try / handle proposé (mais controversé)
    • ? operator pour propager les erreurs
    • Meilleure ergonomie
  3. Pattern matching :

    • Match expressions
    • Destructuring
    • Type patterns enrichis
  4. Immutabilité :

    • const pour les variables
    • Immutable structs
    • Valeurs défensives
  5. Modules v2 :

    • Meilleure résolution des dépendances
    • Registry privé
    • Build reproducibility améliorée

Défis

  • Backward compatibility : la promesse Go 1.x
  • Complexity budget : ne pas devenir Java
  • Tooling : tout l'écosystème à mettre à jour

La philosophie Go 2.0

D'après les talks de Russ Cox (GopherCon 2023, 2024) :

"Go 2.0 n'est pas une réécriture, c'est une évolution. Nous voulons préserver ce qui rend Go génial : la simplicité, la productivité, et la performance."

Principes :

  • Go 1.x continue d'être supporté
  • Migration automatique (go fix)
  • Pas de breaking changes sans nécessité absolue
  • Chaque feature doit simplifier plus qu'elle ne complexifie

Ce qui ne changera PAS

  • Goroutines et channels (modèle CSP)
  • Interfaces structurelles (duck typing)
  • Compilation rapide
  • Binaire statique unique
  • Garbage collector concurrent
  • gofmt standardisation
  • Pas de classes/héritage

Résumé des tendances

TendanceImpactQuandRecommandation
Iterators★★★★★2024-2025Adopter immédiatement
Generics★★★★2023-2026Adopter pour les conteneurs
WASM★★★2023-2027Surveiller, adopter pour edge
AI/ML serving★★★★2024-2026Adopter pour l'infra ML
Stdlib renaissance★★★★2023-2025Réduire les dépendances
Embedded (TinyGo)★★★2024-2028Surveiller, cas spécifique
Go 2.0★★2026-2028Pas de décision urgente

Conseils pour rester à jour

  1. Suivre le Go Blog : chaque release a un article détaillé
  2. GopherCon talks : YouTube, slides
  3. Go Release Notes : lisez chaque release notes
  4. Contributeur à un projet Go : meilleur moyen de suivre
  5. GoTip : newsletter, issues GitHub

Les 5 choses à retenir

  1. Les iterators changent la donne : adoptez-les dans vos APIs
  2. Le stdlib est suffisant : avant d'ajouter une dépendance, vérifiez si le stdlib ne fait pas le job
  3. Go + Cloud = dominant : serveurs, microservices, edge
  4. Go + AI = infrastructure : model serving, data pipelines
  5. Go évolue, mais ne change pas : la philosophie reste la même