MFormations
Modern Go Engineering

Chapitre 0

00 - Introduction à Go

00 - Introduction à Go

Cours 00 : Introduction à Go

1. Histoire de Go

1.1 Les origines (2007)

En septembre 2007, Robert Griesemer, Rob Pike et Ken Thompson (trois ingénieurs chez Google) ont commencé à esquisser les objectifs d'un nouveau langage. Les motivations principales étaient :

  • Temps de compilation trop longs : Les gros projets C++ chez Google mettaient des heures à compiler
  • Gestion des dépendances chaotique : Les systèmes de build comme make devenaient ingérables
  • Concurrence difficile : Les threads et locks en C++/Java étaient source d'erreurs
  • Manque d'outillage moderne : Pas de formatteur automatique, pas de gestionnaire de paquets standard

Le nom "Go" a été choisi pour sa simplicité et sa signification en anglais. Le logo (le gopher) a été conçu par Renée French (épouse de Rob Pike).

1.2 Les premières versions (2008-2011)

// Hello World en Go (2009)
package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}
  • Novembre 2009 : Go est annoncé publiquement en open source (licence BSD)
  • Janvier 2010 : La documentation en ligne (golang.org) est lancée
  • Mai 2010 : Go 1.0 est planifié, le compilateur est réécrit en Go (bootstrapping)
  • Mars 2011 : Le go tool est introduit (gofmt, gobuild, gotest)

1.3 La maturité (2012-2018)

  • Mars 2012 : Go 1.0 est publié avec la promesse de compatibilité ascendante
  • 2013 : Adoption par Docker, Kubernetes, Terraform
  • 2015 : Go 1.5 réécrit entièrement en Go (fin du C)
  • 2016 : Introduction de vendor pour les dépendances
  • 2018 : Go modules expérimentaux (Go 1.11)

1.4 L'ère moderne (2019-2024)

  • 2019 : Go 1.13, go modules par défaut
  • 2020 : Go 1.15, améliorations du compilateur (20-30% plus rapide)
  • 2021 : Go 1.17-1.18, generics enfin !
  • 2022 : Go 1.19-1.20, améliorations de la sécurité
  • 2023 : Go 1.21-1.22, boucles améliorées, toolchain management
  • 2024 : Go 1.23, itérateurs de fonction, améliorations du runtime
// Go 1.18+ : Generics
func Map[T any](s []T, f func(T) T) []T {
    result := make([]T, len(s))
    for i, v := range s {
        result[i] = f(v)
    }
    return result
}

// Go 1.22+ : Boucle for améliorée
for i := range 10 {
    fmt.Println(i)
}

2. Philosophie de Go

2.1 La simplicité comme principe fondamental

Go a été conçu avec une philosophie radicale de simplicité :

// Pas de classes, pas d'héritage
type Animal struct {
    Name string
}

// Les interfaces sont implicites
type Speaker interface {
    Speak() string
}

func (a Animal) Speak() string {
    return a.Name + " says hello"
}

// Utilisation
var s Speaker = Animal{Name: "Dog"}
fmt.Println(s.Speak())

Principes clés :

  • Moins de features : Pas de classes, pas d'héritage, pas d'exceptions, pas de génériques (jusque 1.18)
  • Lisibilité > brièveté : Pas de syntaxe implicite, pas de sucre syntaxique excessif
  • Explicite > implicite : Les conversions sont explicites, les erreurs sont des valeurs

2.2 La concurrence comme citoyenne de première classe

// Une goroutine : un mot-clé
go func() {
    fmt.Println("Exécuté en parallèle")
}()

// Les channels comme primitive de synchronisation
ch := make(chan string)
go func() {
    ch <- "message"
}()
msg := <-ch

2.3 Les piliers philosophiques

1. Faites les choses correctement par défaut

// gofmt formate automatiquement
func add(x int, y int) int { return x + y }

2. Communiquez via la mémoire partagée

// "Do not communicate by sharing memory; instead, share memory by communicating."
ch := make(chan int)

3. Zéro valeur utile

var i int       // 0
var s string    // ""
var b bool      // false
var p *int      // nil

4. Les erreurs sont des valeurs

f, err := os.Open("file.txt")
if err != nil {
    return fmt.Errorf("ouverture fichier: %w", err)
}

3. Écosystème et outils

3.1 La toolchain Go

go version          # Version de Go installée
go env              # Configuration Go
go fmt              # Formattage automatique
go build            # Compilation
go run              # Compilation + exécution
go test             # Tests unitaires
go mod init         # Initialisation d'un module
go mod tidy         # Nettoyage des dépendances
go vet              # Analyse statique
go doc              # Documentation

3.2 Les outils essentiels

gofmt / goimports

// Avant gofmt :
func  add( x  int,  y int )int{ return x+y;}

// Après gofmt :
func add(x int, y int) int { return x + y }

go vet

func main() {
    s := "hello"
    fmt.Printf("%d", s) // go vet détecte cette erreur de format
}

3.3 Les modules Go (go mod)

// go.mod
module github.com/user/project

go 1.23

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/go-sql-driver/mysql v1.7.1
)

3.4 Les outils communautaires

OutilUtilitéCommande
golangci-lintLinting completgolangci-lint run
delveDebuggerdlv debug
go-swaggerDocumentation APIswagger generate
mockgenGénération de mocksmockgen -source=file.go
wireInjection de dépendanceswire

4. Comparaison avec d'autres langages

4.1 Go vs Java

// Go : Simple, rapide à compiler
func sum(a, b int) int { return a + b }

// Équivalent Java
// public static int sum(int a, int b) { return a + b; }
AspectGoJava
SyntaxeMinimalisteVerbose
Compilation~1s~10s+
ConcurrenceGoroutines (2KB stack)Threads (1MB stack)
GénériquesDepuis 1.18Depuis JDK 5
HéritageCompositionClasse
RuntimeCompilé natifJVM

4.2 Go vs Python

// Go : Statiquement typé, compilé
func process(items []string) ([]string, error) {
    result := make([]string, 0, len(items))
    for _, item := range items {
        if len(item) > 0 {
            result = append(result, item)
        }
    }
    return result, nil
}
AspectGoPython
TypageStatiqueDynamique
PerformanceCompilé natifInterprété
ConcurrenceGoroutinesGIL-limited
DéploiementBinaire uniqueRuntime requis
ProductivitéModéréeTrès élevée

4.3 Go vs Rust

// Go : GC, simplicité, rapidité de développement
type Server struct {
    addr string
    pool *sync.Pool
}
AspectGoRust
Gestion mémoireGCOwnership/Borrowing
Courbe apprentissageFaibleÉlevée
ConcurrenceCSP (channels)Async/Sync
PerformanceTrès bonneExcellente
Cas d'usageAPIs, réseauxSystème, embarqué

5. Roadmap et évolution

5.1 Go 1.x (2012-2024+)

Go 1.18 (2022) : Generics

func Max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

Go 1.21 (2023) : Toolchain management

// toolchain directive dans go.mod
toolchain go1.23.0

Go 1.22 (2024) : Boucles améliorées

// Itération sur entiers
for i := range 10 {
    // i va de 0 à 9
}

// Capture correcte dans les boucles
for _, v := range slice {
    go func() {
        fmt.Println(v) // v est correctement capturé
    }()
}

Go 1.23 (2024) : Itérateurs de fonction

// Itérateurs personnalisés
func Backward[E any](s []E) func(func(int, E) bool) {
    return func(yield func(int, E) bool) {
        for i := len(s) - 1; i >= 0; i-- {
            if !yield(i, s[i]) {
                return
            }
        }
    }
}

5.2 Futures directions

  1. Amélioration des generics : Meilleure inférence, types de type supérieur
  2. Zero-cost abstractions : Optimisation des interfaces et goroutines
  3. Meilleur support WASM : WebAssembly cible de première classe
  4. Telemetry : Collecte de données d'utilisation (opt-in)
  5. Tooling : Amélioration continue de l'éditeur LSP (gopls)

Résumé

  • Go a été créé en 2007 chez Google pour résoudre des problèmes concrets
  • La philosophie repose sur la simplicité, la lisibilité et la concurrence
  • L'écosystème est riche avec gofmt, go mod, go test, etc.
  • Go se positionne idéalement pour les APIs, le cloud, et les outils systèmes
  • La roadmap montre une évolution prudente mais régulière

Exercices

  1. Installation : Installez Go 1.22+, configurez votre GOPATH
  2. Premier programme : Écrivez "Hello, 世界" et observez le support Unicode
  3. Outils : Testez gofmt, go vet, go doc sur un petit programme
  4. Benchmark : Comparez temps de compilation Go vs C++ vs Java
  5. Concurrence basique : Lancez 1000 goroutines et observez l'utilisation mémoire