Passer au contenu principal
eLearner.app
Module 3 · Leçon 4 sur 514/50 dans le cours~12 min
Leçons du module (4/5)

Fermetures et fonctions comme valeurs

Dans Go, les fonctions sont des valeurs de première classe : elles peuvent être affectées à variables, transmises à d’autres fonctions et renvoyées. Une fermeture est un fonction littérale (anonyme) qui capture les variables du environnement dans lequel il est défini.

Fonction littérale

Une fonction sans nom, écrite en ligne. Vous l'appelez immédiatement ou attribuez-le :

Go
greet := func(name string) {
    fmt.Println("ciao", name)
}
greet("Anna")

// invocata immediatamente:
func() { fmt.Println("subito") }()

Le type de greet est func(string).

Capturer l'environnement : clôture

La fonction littérale peut lire et modifier les variables visibles dans sa portée lexicale, même après le retour de la fonction externe :

Go
func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

c := counter()
fmt.Println(c(), c(), c())  // 1 2 3

n "vit" tant qu'au moins une fermeture y fait référence. Chaque appel à counter() crée un nouveau n indépendant.

Fermeture comme rappel

Un modèle très courant :

Go
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
    return nums[i] < nums[j]
})

La fermeture capture nums et définit l'ordre.

Fonctions comme paramètres

Pour accepter une fonction en paramètre, écrivez son type :

Go
func apply(nums []int, f func(int) int) []int {
    out := make([]int, len(nums))
    for i, n := range nums {
        out[i] = f(n)
    }
    return out
}

double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double)   // [2 4 6]

Si la signature devient difficile à lire, définissez un type alias :

Go
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }

Essayez-le

Exercice#go.m3.l4.e1
Tentatives : 0Chargement…

Définissez counter() qui renvoie une fermeture : chaque appel à la fermeture s'incrémente et renvoie un compteur interne.

Chargement de l'éditeur…
Afficher l'indice

`n` doit être déclaré AVANT le retour ; la fermeture le capture.

Solution disponible après 3 tentatives

Exercice#go.m3.l4.e2
Tentatives : 0Chargement…

Attribuez à f une fonction littérale qui imprime 'ciao', puis appelez-la.

Chargement de l'éditeur…
Afficher l'indice

Syntaxe : `f := func() { ... }` puis `f()`.

Solution disponible après 3 tentatives

Quiz#go.m3.l4.e3
Prêt

Qu'est-ce que cela imprime ? (attention à la portée de fermeture)

Go
mk := func() func() int {
    x := 0
    return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())
Options de réponse

Récapitulatif

  • Les fonctions sont de première classe : assignables, passables, consignées.
  • Littéral de fonction : func(params) ret { ... }, anonyme.
  • Fermeture : capture les variables de la portée lexicale, les maintient en vie.
  • Type de fonction explicite en paramètres : func(int) int.
  • Depuis Go 1.22, chaque itération for possède sa propre copie de la variable de boucle.